load devices, show menu, view entities

This commit is contained in:
Nitwel 2023-10-30 01:21:50 +01:00
parent 97aa0f723a
commit d24f3a7c7e
18 changed files with 262 additions and 42 deletions

12
.editorconfig Normal file
View File

@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = tab
indent_size = 4
end_of_line = crlf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:55d5f30db336a8f8f7633743c23e41077d5c1a1b900c475a6d3811746eba3d1b
size 141

View File

@ -1 +0,0 @@
<svg height="128" width="128" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="124" height="124" rx="14" fill="#363d52" stroke="#212532" stroke-width="4"/><g transform="scale(.101) translate(122 122)"><g fill="#fff"><path d="M105 673v33q407 354 814 0v-33z"/><path fill="#478cbf" d="m105 673 152 14q12 1 15 14l4 67 132 10 8-61q2-11 15-15h162q13 4 15 15l8 61 132-10 4-67q3-13 15-14l152-14V427q30-39 56-81-35-59-83-108-43 20-82 47-40-37-88-64 7-51 8-102-59-28-123-42-26 43-46 89-49-7-98 0-20-46-46-89-64 14-123 42 1 51 8 102-48 27-88 64-39-27-82-47-48 49-83 108 26 42 56 81zm0 33v39c0 276 813 276 813 0v-39l-134 12-5 69q-2 10-14 13l-162 11q-12 0-16-11l-10-65H447l-10 65q-4 11-16 11l-162-11q-12-3-14-13l-5-69z"/><path d="M483 600c3 34 55 34 58 0v-86c-3-34-55-34-58 0z"/><circle cx="725" cy="526" r="90"/><circle cx="299" cy="526" r="90"/></g><g fill="#414042"><circle cx="307" cy="532" r="60"/><circle cx="717" cy="532" r="60"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 950 B

View File

@ -1,37 +0,0 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://bnc4gf261swvs"
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.svg"
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
svg/scale=1.0
editor/scale_with_editor_scale=false
editor/convert_colors_with_editor_theme=false

View File

@ -1,9 +1,10 @@
[gd_scene load_steps=12 format=3 uid="uid://eecv28y6jxk4"] [gd_scene load_steps=13 format=3 uid="uid://eecv28y6jxk4"]
[ext_resource type="Script" path="res://src/devices/light.gd" id="1_5mqma"]
[ext_resource type="PackedScene" uid="uid://clc5dre31iskm" path="res://addons/godot-xr-tools/xr/start_xr.tscn" id="1_i4c04"] [ext_resource type="PackedScene" uid="uid://clc5dre31iskm" path="res://addons/godot-xr-tools/xr/start_xr.tscn" id="1_i4c04"]
[ext_resource type="Script" path="res://src/raycast.gd" id="1_tsqxc"] [ext_resource type="Script" path="res://src/raycast.gd" id="1_tsqxc"]
[ext_resource type="Script" path="res://src/model.gd" id="2_7f1x4"] [ext_resource type="Script" path="res://src/model.gd" id="2_7f1x4"]
[ext_resource type="Script" path="res://light.gd" id="4_bm5yj"] [ext_resource type="PackedScene" uid="uid://c3kdssrmv84kv" path="res://scenes/menu.tscn" id="3_1tbp3"]
[sub_resource type="SphereShape3D" id="SphereShape3D_2igmd"] [sub_resource type="SphereShape3D" id="SphereShape3D_2igmd"]
radius = 0.1 radius = 0.1
@ -42,7 +43,7 @@ ambient_light_sky_contribution = 0.72
[node name="Light" type="StaticBody3D" parent="."] [node name="Light" type="StaticBody3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.45064, 0, 0.20152) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.45064, 0, 0.20152)
script = ExtResource("4_bm5yj") script = ExtResource("1_5mqma")
[node name="CollisionShape3D" type="CollisionShape3D" parent="Light"] [node name="CollisionShape3D" type="CollisionShape3D" parent="Light"]
shape = SubResource("SphereShape3D_2igmd") shape = SubResource("SphereShape3D_2igmd")
@ -67,6 +68,9 @@ mesh = SubResource("BoxMesh_ir3co")
script = ExtResource("2_7f1x4") script = ExtResource("2_7f1x4")
light = NodePath("../../../Light") light = NodePath("../../../Light")
[node name="Menu" parent="XROrigin3D/XRControllerLeft" instance=ExtResource("3_1tbp3")]
transform = Transform3D(-4.37114e-08, 0, -1, -0.707107, 0.707107, 3.09086e-08, 0.707107, 0.707107, -3.09086e-08, 0.194945, 0, -0.0534939)
[node name="XRControllerRight" type="XRController3D" parent="XROrigin3D"] [node name="XRControllerRight" type="XRController3D" parent="XROrigin3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.488349, 0.559219, -0.2988) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.488349, 0.559219, -0.2988)
tracker = &"right_hand" tracker = &"right_hand"

View File

@ -13,11 +13,12 @@ config_version=5
config/name="ImmersiveHome" config/name="ImmersiveHome"
run/main_scene="res://main.tscn" run/main_scene="res://main.tscn"
config/features=PackedStringArray("4.1", "Mobile") config/features=PackedStringArray("4.1", "Mobile")
config/icon="res://icon.svg"
[autoload] [autoload]
XRToolsUserSettings="*res://addons/godot-xr-tools/user_settings/user_settings.gd" XRToolsUserSettings="*res://addons/godot-xr-tools/user_settings/user_settings.gd"
Request="*res://src/globals/request.gd"
HomeAdapters="*res://src/globals/home_adapters.gd"
[editor_plugins] [editor_plugins]

23
scenes/device.tscn Normal file
View File

@ -0,0 +1,23 @@
[gd_scene load_steps=4 format=3 uid="uid://dbe8slnyhro2n"]
[ext_resource type="Script" path="res://src/ui/device.gd" id="1_rbo86"]
[sub_resource type="BoxMesh" id="BoxMesh_aa3i4"]
size = Vector3(0.05, 0.01, 0.05)
[sub_resource type="BoxShape3D" id="BoxShape3D_28fjq"]
size = Vector3(0.05, 0.01, 0.05)
[node name="Device" type="StaticBody3D"]
script = ExtResource("1_rbo86")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_aa3i4")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("BoxShape3D_28fjq")
[node name="Label" type="Label3D" parent="."]
transform = Transform3D(-2.18557e-09, -0.05, -2.18557e-09, 0, -2.18557e-09, 0.05, -0.05, 2.18557e-09, 9.55343e-17, 0, 0.00918245, 0)
text = "Text"
autowrap_mode = 3

23
scenes/entity.tscn Normal file
View File

@ -0,0 +1,23 @@
[gd_scene load_steps=4 format=3 uid="uid://xo0o5nrfjl23"]
[ext_resource type="Script" path="res://src/ui/entity.gd" id="1_825oj"]
[sub_resource type="BoxMesh" id="BoxMesh_aa3i4"]
size = Vector3(0.05, 0.01, 0.05)
[sub_resource type="BoxShape3D" id="BoxShape3D_28fjq"]
size = Vector3(0.05, 0.01, 0.05)
[node name="Entity" type="StaticBody3D"]
script = ExtResource("1_825oj")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("BoxMesh_aa3i4")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("BoxShape3D_28fjq")
[node name="Label" type="Label3D" parent="."]
transform = Transform3D(-2.18557e-09, -0.05, -2.18557e-09, 0, -2.18557e-09, 0.05, -0.05, 2.18557e-09, 9.55343e-17, 0, 0.00918245, 0)
text = "Text"
autowrap_mode = 3

17
scenes/menu.tscn Normal file
View File

@ -0,0 +1,17 @@
[gd_scene load_steps=4 format=3 uid="uid://c3kdssrmv84kv"]
[ext_resource type="Script" path="res://src/menu.gd" id="1_ng4u3"]
[ext_resource type="Material" uid="uid://bertj8bp8b5l1" path="res://assets/materials/interface.tres" id="2_nsukb"]
[sub_resource type="PlaneMesh" id="PlaneMesh_6t3dn"]
material = ExtResource("2_nsukb")
size = Vector2(0.3, 0.3)
[node name="Menu" type="Node3D"]
script = ExtResource("1_ng4u3")
[node name="Background" type="MeshInstance3D" parent="."]
mesh = SubResource("PlaneMesh_6t3dn")
[node name="Devices" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -0.149223, 0, 0.150667)

View File

@ -0,0 +1,6 @@
extends Node
var Adapter = preload("res://src/home_adapters/adapter.gd")
var adapter = Adapter.new(Adapter.ADAPTER_TYPES.HASS)

1
src/globals/request.gd Normal file
View File

@ -0,0 +1 @@
extends HTTPRequest

View File

@ -0,0 +1,26 @@
extends Node
const hass = preload("res://src/home_adapters/hass/hass.gd")
enum ADAPTER_TYPES {
HASS
}
const adapters = {
ADAPTER_TYPES.HASS: hass
}
const methods = [
"load_devices"
]
var adapter: Node
func _init(type: ADAPTER_TYPES):
adapter = adapters[type].new()
for method in methods:
assert(adapter.has_method(method), "Adapter does not implement method: " + method)
func load_devices():
return await adapter.load_devices()

View File

@ -0,0 +1,23 @@
extends Node
var url: String = "http://192.168.33.33:8123"
var token: String = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzZjQ0ZGM2N2Y3YzY0MDc1OGZlMWI2ZjJlNmIxZjRkNSIsImlhdCI6MTY5ODAxMDcyOCwiZXhwIjoyMDEzMzcwNzI4fQ.K6ydLUC-4Q7BNIRCU1nWlI2s6sg9UCiOu-Lpedw2zJc"
var headers: PackedStringArray = PackedStringArray([])
var devices_template = FileAccess.get_file_as_string("res://src/home_adapters/hass/templates/devices.j2")
func _init(url := self.url, token := self.token):
self.url = url
self.token = token
headers = PackedStringArray(["Authorization: Bearer %s" % token, "Content-Type: application/json"])
devices_template = devices_template.replace("\n", " ").replace("\t", "").replace("\r", " ").replace("\"", "\\\"")
func load_devices():
Request.request("%s/api/template" % [url], headers, HTTPClient.METHOD_POST, "{\"template\": \"%s\"}" % [devices_template])
var response = await Request.request_completed
var data_string = response[3].get_string_from_utf8().replace("'", "\"")
var json = JSON.parse_string(data_string).data
print(json)
return json

View File

@ -0,0 +1,12 @@
{% set devices = states | map(attribute='entity_id') | map('device_id') | unique | reject('eq',None) | list %}
{%- set ns = namespace(devices = []) %}
{%- for device in devices %}
{%- set entities = device_entities(device) | list %}
{%- if entities %}
{%- set ns.devices = ns.devices + [ {device: {"name": device_attr(device, "name"), "entities": entities }} ] %}
{%- endif %}
{%- endfor %}
{
"data": {{ ns.devices }}
}

83
src/menu.gd Normal file
View File

@ -0,0 +1,83 @@
extends Node3D
const Device = preload("res://scenes/device.tscn")
const Entity = preload("res://scenes/entity.tscn")
@onready var devices_node = $Devices
var devices
var selected_device = null
# Called when the node enters the scene tree for the first time.
func _ready():
devices = await HomeAdapters.adapter.load_devices()
render_devices()
func render_devices():
var x = 0
var y = 0
for device in devices:
var info = device.values()[0]
var device_instance = Device.instantiate()
device_instance.set_position(Vector3(y * 0.08, 0, -x * 0.08))
device_instance.click.connect(_on_device_click)
devices_node.add_child(device_instance)
device_instance.set_device_name(info["name"])
x += 1
if x % 5 == 0:
x = 0
y += 1
func render_entities():
var x = 0
var y = 0
var info
for device in devices:
if device.values()[0].name == selected_device:
info = device.values()[0]
break
if info == null:
return
var entities = info["entities"]
for entity in entities:
var entity_instance = Entity.instantiate()
entity_instance.set_position(Vector3(y * 0.08, 0, -x * 0.08))
entity_instance.click.connect(_on_entity_click)
devices_node.add_child(entity_instance)
entity_instance.set_entity_name(entity)
x += 1
if x % 5 == 0:
x = 0
y += 1
func _on_device_click(device_name):
selected_device = device_name
print(selected_device)
clear_menu()
render_entities()
func _on_entity_click(entity_name):
print(entity_name)
selected_device = null
clear_menu()
render_devices()
func clear_menu():
for child in devices_node.get_children():
devices_node.remove_child(child)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

12
src/ui/device.gd Normal file
View File

@ -0,0 +1,12 @@
extends StaticBody3D
@onready var label: Label3D = $Label
signal click(name: String)
func _on_toggle():
click.emit(label.text)
func set_device_name(text):
assert(label != null, "Device has to be added to the scene tree")
label.text = text

12
src/ui/entity.gd Normal file
View File

@ -0,0 +1,12 @@
extends StaticBody3D
@onready var label: Label3D = $Label
signal click(name: String)
func _on_toggle():
click.emit(label.text)
func set_entity_name(text):
assert(label != null, "Entity has to be added to the scene tree")
label.text = text