.github | ||
addons | ||
android | ||
assets | ||
content | ||
lib | ||
.editorconfig | ||
.gitattributes | ||
.gitignore | ||
editor_settings-4.tres | ||
export_presets_prod.cfg | ||
export_presets.cfg | ||
openxr_action_map.tres | ||
project.godot | ||
README.md |
🏠 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
Mixed Reality Headsets
- Meta Quest 2 / Pro / 3
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.
🛠 Development
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.
File Structure
.
├── addons (All installed Godot Addons are saved here)
├── assets (Files like logos or assets that are shared across scenes)
├── content/ (Main files of the project)
│ ├── entities (Entities that can be placed into the room)
│ ├── functions (Generic functions that can be used in scenes)
│ └── ui (User Interface Scenes and related files)
└── lib/ (Code that is global or shared across scenes)
├── globals (Globally running scripts)
└── home_adapters (Code allowing control smart home entities)
Home Adapters
The HomeAdapters
global allows to communicate with different backends and offers a set of fundamental functions allowing communication with the Smart Home.
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
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.
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.
It is also possible to bubble up information by returning a dictionary from a function like _on_click
.
Function called | Args | Description |
---|---|---|
_on_click |
[event: EventRay] |
The back trigger button has been pressed and released |
_on_press_down |
[event: EventRay] |
The back trigger button has been pressed down |
_on_press_move |
[event: EventRay] |
The back trigger button has been moved while pressed down |
_on_press_up |
[event: EventRay] |
The back trigger button has been released |
_on_grab_down |
[event: EventRay] |
The side grab button been pressed down |
_on_grab_move |
[event: EventRay] |
The side grab button been pressed down |
_on_grab_up |
[event: EventRay] |
The side grab button been released |
_on_ray_enter |
[event: EventRay] |
The ray-cast enters the the collision body |
_on_ray_leave |
[event: EventRay] |
The ray-cast leaves the the collision body |
_on_key_down |
[event: EventKey] |
The ray-cast leaves the the collision body |
_on_key_up |
[event: EventKey] |
The ray-cast leaves the the collision body |
_on_focus_in |
[event: EventFocus] |
The node is got focused |
_on_focus_out |
[event: EventFocus] |
The node lost focus |
After considering using the build in godot event system, I've decided that it would be better to use a custom event system. The reason being that we would have to check each tick if the event matches the desired one which seems very inefficient compared to using signals like the browser does. Thus I've decided to use a custom event system that is similar to the one used in the browser.
UI Groups
Group | Description |
---|---|
ui_focus |
The element can be focused |
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.
Installing Locally
- Make sure Git LFS is installed
- Run
git clone https://github.com/Nitwel/Immersive-Home.git
in your terminal - Import the created
Immersive-Home
folder in Godot - Open the project in Godot 4.1.3
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 asset. Click at the link to get a list of the supported controls.
Building
- Possibly fix importing scenes error
- Follow the following guide to setup exporting for android. link
- Make sure to reuse any existing
debug.keystore
when updating an app - Don't forget to set the JAVA_HOME variable and restart Godot to take effect
- Install the
Godot XR Android OpenXR Loaders
plugin in Godot - Configure the following in the android build template:
- 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
<uses-feature android:name="com.oculus.feature.CONTEXTUAL_BOUNDARYLESS_APP" android:required="true" />
can be added to theAndroidManifest.xml
to disable the boundary system.