rework to HomeApi and fix device loading
This commit is contained in:
parent
e1f9969986
commit
eb327121b8
|
@ -36,7 +36,7 @@ In order to contribute to this project, you need the following to be setup befor
|
||||||
|
|
||||||
## Fundamentals
|
## Fundamentals
|
||||||
|
|
||||||
Communication with the Smart Home Environment is done using the `HomeAdapters` global. Each environment is made up of devices and entities.
|
Communication with the Smart Home Environment is done using the `HomeApi` 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.
|
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.
|
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.
|
||||||
|
|
||||||
|
@ -55,9 +55,9 @@ For example, the entity of name `lights.smart_lamp_1` would control the kitchen
|
||||||
└── home_adapters (Code allowing control smart home entities)
|
└── home_adapters (Code allowing control smart home entities)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Home Adapters
|
### Home Api
|
||||||
|
|
||||||
The `HomeAdapters` global allows to communicate with different backends and offers a set of fundamental functions allowing communication with the Smart Home.
|
The `HomeApi` global allows to communicate with different backends and offers a set of fundamental functions allowing communication with the Smart Home.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
Device {
|
Device {
|
||||||
|
|
3
assets/icons/wifi_white_24dp.svg
Normal file
3
assets/icons/wifi_white_24dp.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:053d1e42a72e988fad4b2ef981eb72ec850f1f7da6963b257c8935e8392cb37b
|
||||||
|
size 324
|
39
assets/icons/wifi_white_24dp.svg.import
Normal file
39
assets/icons/wifi_white_24dp.svg.import
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://co5fgm68t4j6o"
|
||||||
|
path.s3tc="res://.godot/imported/wifi_white_24dp.svg-9edf937c7c00e607b2e1a7211dd6ea49.s3tc.ctex"
|
||||||
|
path.etc2="res://.godot/imported/wifi_white_24dp.svg-9edf937c7c00e607b2e1a7211dd6ea49.etc2.ctex"
|
||||||
|
metadata={
|
||||||
|
"imported_formats": ["s3tc_bptc", "etc2_astc"],
|
||||||
|
"vram_texture": true
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://assets/icons/wifi_white_24dp.svg"
|
||||||
|
dest_files=["res://.godot/imported/wifi_white_24dp.svg-9edf937c7c00e607b2e1a7211dd6ea49.s3tc.ctex", "res://.godot/imported/wifi_white_24dp.svg-9edf937c7c00e607b2e1a7211dd6ea49.etc2.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=2
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=true
|
||||||
|
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=0
|
||||||
|
svg/scale=8.0
|
||||||
|
editor/scale_with_editor_scale=false
|
||||||
|
editor/convert_colors_with_editor_theme=false
|
|
@ -13,10 +13,10 @@ var brightness = 0 # 0-255
|
||||||
|
|
||||||
# Called when the node enters the scene tree for the first time.
|
# Called when the node enters the scene tree for the first time.
|
||||||
func _ready():
|
func _ready():
|
||||||
var stateInfo = await HomeAdapters.adapter.get_state(entity_id)
|
var stateInfo = await HomeApi.get_state(entity_id)
|
||||||
set_state(stateInfo["state"] == "on")
|
set_state(stateInfo["state"] == "on")
|
||||||
|
|
||||||
await HomeAdapters.adapter.watch_state(entity_id, func(new_state):
|
await HomeApi.watch_state(entity_id, func(new_state):
|
||||||
if (new_state["state"] == "on") == state:
|
if (new_state["state"] == "on") == state:
|
||||||
return
|
return
|
||||||
set_state(new_state["state"] == "on")
|
set_state(new_state["state"] == "on")
|
||||||
|
@ -44,7 +44,7 @@ func _on_click(event):
|
||||||
if !state && brightness != null:
|
if !state && brightness != null:
|
||||||
attributes["brightness"] = int(brightness)
|
attributes["brightness"] = int(brightness)
|
||||||
|
|
||||||
HomeAdapters.adapter.set_state(entity_id, "on" if !state else "off", attributes)
|
HomeApi.set_state(entity_id, "on" if !state else "off", attributes)
|
||||||
set_state(!state, brightness)
|
set_state(!state, brightness)
|
||||||
else:
|
else:
|
||||||
_on_clickable_on_click(event)
|
_on_clickable_on_click(event)
|
||||||
|
@ -71,5 +71,5 @@ func _on_clickable_on_click(event):
|
||||||
|
|
||||||
slider_knob.position = new_pos
|
slider_knob.position = new_pos
|
||||||
|
|
||||||
HomeAdapters.adapter.set_state(entity_id, "on" if state else "off", {"brightness": int(ratio * 255)})
|
HomeApi.set_state(entity_id, "on" if state else "off", {"brightness": int(ratio * 255)})
|
||||||
set_state(state, ratio * 255)
|
set_state(state, ratio * 255)
|
||||||
|
|
|
@ -5,10 +5,10 @@ extends StaticBody3D
|
||||||
|
|
||||||
# Called when the node enters the scene tree for the first time.
|
# Called when the node enters the scene tree for the first time.
|
||||||
func _ready():
|
func _ready():
|
||||||
var stateInfo = await HomeAdapters.adapter.get_state(entity_id)
|
var stateInfo = await HomeApi.get_state(entity_id)
|
||||||
set_text(stateInfo)
|
set_text(stateInfo)
|
||||||
|
|
||||||
await HomeAdapters.adapter.watch_state(entity_id, func(new_state):
|
await HomeApi.watch_state(entity_id, func(new_state):
|
||||||
set_text(new_state)
|
set_text(new_state)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ extends StaticBody3D
|
||||||
|
|
||||||
# Called when the node enters the scene tree for the first time.
|
# Called when the node enters the scene tree for the first time.
|
||||||
func _ready():
|
func _ready():
|
||||||
var stateInfo = await HomeAdapters.adapter.get_state(entity_id)
|
var stateInfo = await HomeApi.get_state(entity_id)
|
||||||
if stateInfo == null:
|
if stateInfo == null:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ func _ready():
|
||||||
else:
|
else:
|
||||||
sprite.set_frame(1)
|
sprite.set_frame(1)
|
||||||
|
|
||||||
await HomeAdapters.adapter.watch_state(entity_id, func(new_state):
|
await HomeApi.watch_state(entity_id, func(new_state):
|
||||||
if new_state["state"] == "on":
|
if new_state["state"] == "on":
|
||||||
sprite.set_frame(0)
|
sprite.set_frame(0)
|
||||||
else:
|
else:
|
||||||
|
@ -23,7 +23,7 @@ func _ready():
|
||||||
|
|
||||||
|
|
||||||
func _on_click(event):
|
func _on_click(event):
|
||||||
HomeAdapters.adapter.set_state(entity_id, "off" if sprite.get_frame() == 0 else "on")
|
HomeApi.set_state(entity_id, "off" if sprite.get_frame() == 0 else "on")
|
||||||
if sprite.get_frame() == 0:
|
if sprite.get_frame() == 0:
|
||||||
sprite.set_frame(1)
|
sprite.set_frame(1)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -84,7 +84,7 @@ func _on_button_released(button: String):
|
||||||
last_collided = null
|
last_collided = null
|
||||||
moved = false
|
moved = false
|
||||||
|
|
||||||
func _emit_event(type: String, target: Object):
|
func _emit_event(type: String, target):
|
||||||
var event = EventRay.new()
|
var event = EventRay.new()
|
||||||
event.controller = controller
|
event.controller = controller
|
||||||
event.target = target
|
event.target = target
|
||||||
|
|
|
@ -19,7 +19,8 @@ var text_handler = preload("res://content/ui/components/input/text_handler.gd").
|
||||||
get:
|
get:
|
||||||
return text_handler.text
|
return text_handler.text
|
||||||
set(value):
|
set(value):
|
||||||
text_handler.set_text(value, EventSystem.is_focused(self) == false)
|
var focused = Engine.is_editor_hint() == false && EventSystem.is_focused(self) == false
|
||||||
|
text_handler.set_text(value, focused)
|
||||||
|
|
||||||
if label != null:
|
if label != null:
|
||||||
label.text = text_handler.get_display_text()
|
label.text = text_handler.get_display_text()
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
|
|
||||||
[sub_resource type="BoxMesh" id="BoxMesh_kjbca"]
|
[sub_resource type="BoxMesh" id="BoxMesh_kjbca"]
|
||||||
resource_local_to_scene = true
|
resource_local_to_scene = true
|
||||||
size = Vector3(0.15, 0.006, 0.03)
|
size = Vector3(0.2, 0.006, 0.03)
|
||||||
|
|
||||||
[sub_resource type="BoxShape3D" id="BoxShape3D_x4yp8"]
|
[sub_resource type="BoxShape3D" id="BoxShape3D_x4yp8"]
|
||||||
resource_local_to_scene = true
|
resource_local_to_scene = true
|
||||||
size = Vector3(0.15, 0.006, 0.03)
|
size = Vector3(0.2, 0.006, 0.03)
|
||||||
|
|
||||||
[sub_resource type="SystemFont" id="SystemFont_nbea0"]
|
[sub_resource type="SystemFont" id="SystemFont_nbea0"]
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ _data = {
|
||||||
|
|
||||||
[node name="Input" type="StaticBody3D" groups=["ui_focus"]]
|
[node name="Input" type="StaticBody3D" groups=["ui_focus"]]
|
||||||
script = ExtResource("1_uml3t")
|
script = ExtResource("1_uml3t")
|
||||||
text = "Hello World"
|
width = 0.2
|
||||||
|
|
||||||
[node name="Box" type="MeshInstance3D" parent="."]
|
[node name="Box" type="MeshInstance3D" parent="."]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.003, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.003, 0)
|
||||||
|
@ -67,7 +67,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.003, 0)
|
||||||
shape = SubResource("BoxShape3D_x4yp8")
|
shape = SubResource("BoxShape3D_x4yp8")
|
||||||
|
|
||||||
[node name="Label" type="Label3D" parent="."]
|
[node name="Label" type="Label3D" parent="."]
|
||||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, -0.073, 0.00618291, 0)
|
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, -0.098, 0.00618291, 0)
|
||||||
pixel_size = 0.0004
|
pixel_size = 0.0004
|
||||||
text = "Hello World"
|
text = "Hello World"
|
||||||
font = SubResource("SystemFont_nbea0")
|
font = SubResource("SystemFont_nbea0")
|
||||||
|
|
|
@ -19,11 +19,6 @@ var pages = 0
|
||||||
var selected_device = null
|
var selected_device = null
|
||||||
# Called when the node enters the scene tree for the first time.
|
# Called when the node enters the scene tree for the first time.
|
||||||
func _ready():
|
func _ready():
|
||||||
HomeAdapters.adapter.adapter.on_connect.connect(func():
|
|
||||||
devices = await HomeAdapters.adapter.get_devices()
|
|
||||||
render()
|
|
||||||
)
|
|
||||||
|
|
||||||
next_page_button.get_node("Clickable").on_click.connect(func(_event):
|
next_page_button.get_node("Clickable").on_click.connect(func(_event):
|
||||||
print("next page")
|
print("next page")
|
||||||
next_page()
|
next_page()
|
||||||
|
@ -33,6 +28,26 @@ func _ready():
|
||||||
previous_page()
|
previous_page()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func _enter_tree():
|
||||||
|
if HomeApi.has_connected():
|
||||||
|
load_devices()
|
||||||
|
else:
|
||||||
|
HomeApi.on_connect.connect(func():
|
||||||
|
if is_inside_tree():
|
||||||
|
load_devices()
|
||||||
|
)
|
||||||
|
|
||||||
|
func load_devices():
|
||||||
|
if devices.size() == 0:
|
||||||
|
devices = await HomeApi.get_devices()
|
||||||
|
render()
|
||||||
|
|
||||||
|
HomeApi.on_disconnect.connect(func():
|
||||||
|
devices = []
|
||||||
|
if is_inside_tree():
|
||||||
|
render()
|
||||||
|
)
|
||||||
|
|
||||||
func update_pages():
|
func update_pages():
|
||||||
if selected_device == null:
|
if selected_device == null:
|
||||||
pages = ceil(float(devices.size()) / page_size)
|
pages = ceil(float(devices.size()) / page_size)
|
||||||
|
|
|
@ -8,7 +8,7 @@ radius = 0.08
|
||||||
height = 0.16
|
height = 0.16
|
||||||
|
|
||||||
[node name="Ball" type="RigidBody3D"]
|
[node name="Ball" type="RigidBody3D"]
|
||||||
angular_damp = 39.224
|
angular_damp = 4.0
|
||||||
|
|
||||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||||
shape = SubResource("SphereShape3D_orlq6")
|
shape = SubResource("SphereShape3D_orlq6")
|
||||||
|
|
|
@ -25,22 +25,23 @@ func _ready():
|
||||||
input_token.text = config["token"]
|
input_token.text = config["token"]
|
||||||
|
|
||||||
button_connect.on_button_down.connect(func():
|
button_connect.on_button_down.connect(func():
|
||||||
HomeAdapters.adapter.adapter.url = input_url.text + "/api/websocket"
|
var url = input_url.text + "/api/websocket"
|
||||||
HomeAdapters.adapter.adapter.token = input_token.text
|
var token = input_token.text
|
||||||
HomeAdapters.adapter.adapter.retries = 5
|
|
||||||
HomeAdapters.adapter.adapter.connect_ws()
|
HomeApi.start_adapter("hass_ws", url, token)
|
||||||
|
|
||||||
ConfigData.save_config({
|
ConfigData.save_config({
|
||||||
|
"api_type": "hass_ws",
|
||||||
"url": input_url.text,
|
"url": input_url.text,
|
||||||
"token": input_token.text
|
"token": input_token.text
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
HomeAdapters.adapter.adapter.on_connect.connect(func():
|
HomeApi.on_connect.connect(func():
|
||||||
connection_status.text = "Connected"
|
connection_status.text = "Connected"
|
||||||
)
|
)
|
||||||
|
|
||||||
HomeAdapters.adapter.adapter.on_disconnect.connect(func():
|
HomeApi.on_disconnect.connect(func():
|
||||||
connection_status.text = "Disconnected"
|
connection_status.text = "Disconnected"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
[gd_scene load_steps=6 format=3 uid="uid://c6r4higceibif"]
|
[gd_scene load_steps=7 format=3 uid="uid://c6r4higceibif"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://content/ui/menu/settings/settings_menu.gd" id="1_0lte6"]
|
[ext_resource type="Script" path="res://content/ui/menu/settings/settings_menu.gd" id="1_0lte6"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="1_faxng"]
|
[ext_resource type="PackedScene" uid="uid://bsjqdvkt0u87c" path="res://content/ui/components/button/button.tscn" id="1_faxng"]
|
||||||
[ext_resource type="Script" path="res://content/functions/clickable.gd" id="3_qmg6q"]
|
[ext_resource type="Script" path="res://content/functions/clickable.gd" id="3_qmg6q"]
|
||||||
[ext_resource type="PackedScene" uid="uid://blrhy2uccrdn4" path="res://content/ui/components/input/input.tscn" id="4_q3x6k"]
|
[ext_resource type="PackedScene" uid="uid://blrhy2uccrdn4" path="res://content/ui/components/input/input.tscn" id="4_q3x6k"]
|
||||||
|
[ext_resource type="Texture2D" uid="uid://co5fgm68t4j6o" path="res://assets/icons/wifi_white_24dp.svg" id="5_muw54"]
|
||||||
|
|
||||||
[sub_resource type="BoxMesh" id="BoxMesh_e51x8"]
|
[sub_resource type="BoxMesh" id="BoxMesh_e51x8"]
|
||||||
size = Vector3(0.3, 0.01, 0.3)
|
size = Vector3(0.3, 0.01, 0.3)
|
||||||
|
@ -30,40 +31,45 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.0458097, 0, 0.253575)
|
||||||
script = ExtResource("3_qmg6q")
|
script = ExtResource("3_qmg6q")
|
||||||
|
|
||||||
[node name="ConnectionStatus" type="Label3D" parent="Content"]
|
[node name="ConnectionStatus" type="Label3D" parent="Content"]
|
||||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.26, 0, 0.29)
|
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.250698, 0, 0.161303)
|
||||||
pixel_size = 0.0003
|
pixel_size = 0.0003
|
||||||
text = "Disconnected"
|
text = "Disconnected"
|
||||||
|
|
||||||
[node name="LabelURL" type="Label3D" parent="Content"]
|
[node name="LabelURL" type="Label3D" parent="Content"]
|
||||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.01, 0, 0.03)
|
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.01, 0, 0.03)
|
||||||
pixel_size = 0.0005
|
pixel_size = 0.0005
|
||||||
text = "URL"
|
text = "url:
|
||||||
|
"
|
||||||
font_size = 36
|
font_size = 36
|
||||||
horizontal_alignment = 0
|
horizontal_alignment = 0
|
||||||
|
|
||||||
[node name="InputURL" parent="Content" instance=ExtResource("4_q3x6k")]
|
[node name="InputURL" parent="Content" instance=ExtResource("4_q3x6k")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.18, 0, 0.03)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.18, 0, 0.03)
|
||||||
width = 0.2
|
text = "ws://192.168.33.33:8123"
|
||||||
text = ""
|
|
||||||
|
|
||||||
[node name="LabelToken" type="Label3D" parent="Content"]
|
[node name="LabelToken" type="Label3D" parent="Content"]
|
||||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.01, 0, 0.07)
|
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.01, 0, 0.07)
|
||||||
pixel_size = 0.0005
|
pixel_size = 0.0005
|
||||||
text = "TOKEN"
|
text = "token:"
|
||||||
font_size = 36
|
font_size = 36
|
||||||
horizontal_alignment = 0
|
horizontal_alignment = 0
|
||||||
|
|
||||||
[node name="InputToken" parent="Content" instance=ExtResource("4_q3x6k")]
|
[node name="InputToken" parent="Content" instance=ExtResource("4_q3x6k")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.18, 0, 0.07)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.18, 0, 0.07)
|
||||||
width = 0.2
|
text = "..."
|
||||||
text = ""
|
|
||||||
|
|
||||||
[node name="LabelConnect" type="Label3D" parent="Content"]
|
[node name="LabelConnect" type="Label3D" parent="Content"]
|
||||||
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.15, 0, 0.12)
|
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.14, 0, 0.12)
|
||||||
pixel_size = 0.0005
|
pixel_size = 0.0005
|
||||||
text = "TOKEN"
|
text = "Connect"
|
||||||
font_size = 36
|
font_size = 36
|
||||||
horizontal_alignment = 0
|
horizontal_alignment = 0
|
||||||
|
|
||||||
[node name="Connect" parent="Content" instance=ExtResource("1_faxng")]
|
[node name="Connect" parent="Content" instance=ExtResource("1_faxng")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.25, 0, 0.12)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.25, 0, 0.12)
|
||||||
|
|
||||||
|
[node name="Sprite3D" type="Sprite3D" parent="Content"]
|
||||||
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.25, 0.012, 0.12)
|
||||||
|
pixel_size = 0.0002
|
||||||
|
axis = 1
|
||||||
|
texture = ExtResource("5_muw54")
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
extends Node
|
|
||||||
|
|
||||||
const Adapter = preload("res://lib/home_adapters/adapter.gd")
|
|
||||||
|
|
||||||
var adapter = Adapter.new(Adapter.ADAPTER_TYPES.HASS_WS)
|
|
||||||
# var adapter_http = Adapter.new(Adapter.ADAPTER_TYPES.HASS)
|
|
||||||
|
|
||||||
func _ready():
|
|
||||||
add_child(adapter)
|
|
||||||
# add_child(adapter_http)
|
|
||||||
|
|
94
lib/globals/home_api.gd
Normal file
94
lib/globals/home_api.gd
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
extends Node
|
||||||
|
|
||||||
|
const Hass = preload("res://lib/home_apis/hass/hass.gd")
|
||||||
|
const HassWebSocket = preload("res://lib/home_apis/hass_ws/hass.gd")
|
||||||
|
|
||||||
|
|
||||||
|
const apis = {
|
||||||
|
"hass": Hass,
|
||||||
|
"hass_ws": HassWebSocket
|
||||||
|
}
|
||||||
|
|
||||||
|
const methods = [
|
||||||
|
"get_devices",
|
||||||
|
"get_device",
|
||||||
|
"get_state",
|
||||||
|
"set_state",
|
||||||
|
"watch_state"
|
||||||
|
]
|
||||||
|
|
||||||
|
signal on_connect()
|
||||||
|
signal on_disconnect()
|
||||||
|
var api: Node
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
print("HomeApi ready")
|
||||||
|
|
||||||
|
var config = ConfigData.load_config()
|
||||||
|
|
||||||
|
if config.has("api_type") && config.has("url") && config.has("token"):
|
||||||
|
var type = config["api_type"]
|
||||||
|
var url = config["url"] + "/api/websocket"
|
||||||
|
var token = config["token"]
|
||||||
|
|
||||||
|
start_adapter(type, url, token)
|
||||||
|
|
||||||
|
|
||||||
|
func start_adapter(type: String, url: String, token: String):
|
||||||
|
print("Starting adapter: %s" % type)
|
||||||
|
if api != null:
|
||||||
|
api.on_connect.disconnect(_on_connect)
|
||||||
|
api.on_disconnect.disconnect(_on_disconnect)
|
||||||
|
remove_child(api)
|
||||||
|
api.queue_free()
|
||||||
|
api = null
|
||||||
|
|
||||||
|
api = apis[type].new(url, token)
|
||||||
|
add_child(api)
|
||||||
|
|
||||||
|
api.on_connect.connect(func():
|
||||||
|
on_connect.emit()
|
||||||
|
)
|
||||||
|
|
||||||
|
api.on_disconnect.connect(func():
|
||||||
|
on_disconnect.emit()
|
||||||
|
)
|
||||||
|
|
||||||
|
for method in methods:
|
||||||
|
assert(api.has_method(method), "%s Api does not implement method: %s" % [type, method])
|
||||||
|
|
||||||
|
func _on_connect():
|
||||||
|
on_connect.emit()
|
||||||
|
|
||||||
|
func _on_disconnect():
|
||||||
|
on_disconnect.emit()
|
||||||
|
|
||||||
|
func has_connected():
|
||||||
|
if api == null:
|
||||||
|
return false
|
||||||
|
return api.has_connected()
|
||||||
|
|
||||||
|
## Get a list of all devices
|
||||||
|
func get_devices():
|
||||||
|
assert(has_connected(), "Not connected")
|
||||||
|
return await api.get_devices()
|
||||||
|
|
||||||
|
## Get a single device by id
|
||||||
|
func get_device(id: String):
|
||||||
|
assert(has_connected(), "Not connected")
|
||||||
|
return await api.get_device(id)
|
||||||
|
|
||||||
|
## Returns the current state of an entity
|
||||||
|
func get_state(entity: String):
|
||||||
|
assert(has_connected(), "Not connected")
|
||||||
|
return await api.get_state(entity)
|
||||||
|
|
||||||
|
## Updates the state of the entity and returns the resulting state
|
||||||
|
func set_state(entity: String, state: String, attributes: Dictionary = {}):
|
||||||
|
assert(has_connected(), "Not connected")
|
||||||
|
return await api.set_state(entity, state, attributes)
|
||||||
|
|
||||||
|
## 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):
|
||||||
|
assert(has_connected(), "Not connected")
|
||||||
|
return api.watch_state(entity, callback)
|
|
@ -1,61 +0,0 @@
|
||||||
extends Node
|
|
||||||
|
|
||||||
const Hass = preload("res://lib/home_adapters/hass/hass.gd")
|
|
||||||
const HassWebSocket = preload("res://lib/home_adapters/hass_ws/hass.gd")
|
|
||||||
|
|
||||||
enum ADAPTER_TYPES {
|
|
||||||
HASS,
|
|
||||||
HASS_WS
|
|
||||||
}
|
|
||||||
|
|
||||||
const adapters = {
|
|
||||||
ADAPTER_TYPES.HASS: Hass,
|
|
||||||
ADAPTER_TYPES.HASS_WS: HassWebSocket
|
|
||||||
}
|
|
||||||
|
|
||||||
const methods = [
|
|
||||||
"get_devices",
|
|
||||||
"get_device",
|
|
||||||
"get_state",
|
|
||||||
"set_state",
|
|
||||||
"watch_state"
|
|
||||||
]
|
|
||||||
|
|
||||||
var adapter: Node
|
|
||||||
|
|
||||||
func _init(type: ADAPTER_TYPES):
|
|
||||||
|
|
||||||
var url = ""
|
|
||||||
var token = ""
|
|
||||||
var config = ConfigData.load_config()
|
|
||||||
|
|
||||||
if config.has("url"):
|
|
||||||
url = config["url"] + "/api/websocket"
|
|
||||||
if config.has("token"):
|
|
||||||
token = config["token"]
|
|
||||||
|
|
||||||
adapter = adapters[type].new(url, token)
|
|
||||||
add_child(adapter)
|
|
||||||
|
|
||||||
for method in methods:
|
|
||||||
assert(adapter.has_method(method), "Adapter does not implement method: " + method)
|
|
||||||
|
|
||||||
## Get a list of all devices
|
|
||||||
func get_devices():
|
|
||||||
return await adapter.get_devices()
|
|
||||||
|
|
||||||
## Get a single device by id
|
|
||||||
func get_device(id: String):
|
|
||||||
return await adapter.get_device(id)
|
|
||||||
|
|
||||||
## Returns the current state of an entity
|
|
||||||
func get_state(entity: String):
|
|
||||||
return await adapter.get_state(entity)
|
|
||||||
|
|
||||||
## Updates the state of the entity and returns the resulting state
|
|
||||||
func set_state(entity: String, state: String, attributes: Dictionary = {}):
|
|
||||||
return await adapter.set_state(entity, state, attributes)
|
|
||||||
|
|
||||||
## 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):
|
|
||||||
return adapter.watch_state(entity, callback)
|
|
|
@ -4,7 +4,7 @@ var url: String = "http://192.168.33.33:8123"
|
||||||
var token: String = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzZjQ0ZGM2N2Y3YzY0MDc1OGZlMWI2ZjJlNmIxZjRkNSIsImlhdCI6MTY5ODAxMDcyOCwiZXhwIjoyMDEzMzcwNzI4fQ.K6ydLUC-4Q7BNIRCU1nWlI2s6sg9UCiOu-Lpedw2zJc"
|
var token: String = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzZjQ0ZGM2N2Y3YzY0MDc1OGZlMWI2ZjJlNmIxZjRkNSIsImlhdCI6MTY5ODAxMDcyOCwiZXhwIjoyMDEzMzcwNzI4fQ.K6ydLUC-4Q7BNIRCU1nWlI2s6sg9UCiOu-Lpedw2zJc"
|
||||||
var headers: PackedStringArray = PackedStringArray([])
|
var headers: PackedStringArray = PackedStringArray([])
|
||||||
|
|
||||||
var devices_template = FileAccess.get_file_as_string("res://lib/home_adapters/hass/templates/devices.j2")
|
var devices_template = FileAccess.get_file_as_string("res://lib/home_apis/hass/templates/devices.j2")
|
||||||
|
|
||||||
func _init(url := self.url, token := self.token):
|
func _init(url := self.url, token := self.token):
|
||||||
self.url = url
|
self.url = url
|
||||||
|
@ -32,8 +32,6 @@ func get_state(entity: String):
|
||||||
|
|
||||||
return json
|
return json
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func set_state(entity: String, state: String, attributes: Dictionary = {}):
|
func set_state(entity: String, state: String, attributes: Dictionary = {}):
|
||||||
var type = entity.split('.')[0]
|
var type = entity.split('.')[0]
|
||||||
var response
|
var response
|
|
@ -1,6 +1,10 @@
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
var devices_template := FileAccess.get_file_as_string("res://lib/home_adapters/hass_ws/templates/devices.j2")
|
signal on_connect()
|
||||||
|
signal on_disconnect()
|
||||||
|
var connected := false
|
||||||
|
|
||||||
|
var devices_template := FileAccess.get_file_as_string("res://lib/home_apis/hass_ws/templates/devices.j2")
|
||||||
var socket := WebSocketPeer.new()
|
var socket := WebSocketPeer.new()
|
||||||
# in seconds
|
# in seconds
|
||||||
var request_timeout := 10.0
|
var request_timeout := 10.0
|
||||||
|
@ -13,7 +17,7 @@ var token := ""
|
||||||
var LOG_MESSAGES := false
|
var LOG_MESSAGES := false
|
||||||
|
|
||||||
var authenticated := false
|
var authenticated := false
|
||||||
var loading := true
|
|
||||||
var id := 1
|
var id := 1
|
||||||
var entities: Dictionary = {}
|
var entities: Dictionary = {}
|
||||||
var retries := 5
|
var retries := 5
|
||||||
|
@ -21,9 +25,6 @@ var retries := 5
|
||||||
var entitiy_callbacks := CallbackMap.new()
|
var entitiy_callbacks := CallbackMap.new()
|
||||||
var packet_callbacks := CallbackMap.new()
|
var packet_callbacks := CallbackMap.new()
|
||||||
|
|
||||||
signal on_connect()
|
|
||||||
signal on_disconnect()
|
|
||||||
|
|
||||||
func _init(url := self.url, token := self.token):
|
func _init(url := self.url, token := self.token):
|
||||||
self.url = url
|
self.url = url
|
||||||
self.token = token
|
self.token = token
|
||||||
|
@ -114,7 +115,7 @@ func start_subscriptions():
|
||||||
"attributes": packet.event.a[entity]["a"]
|
"attributes": packet.event.a[entity]["a"]
|
||||||
}
|
}
|
||||||
entitiy_callbacks.call_key(entity, [entities[entity]])
|
entitiy_callbacks.call_key(entity, [entities[entity]])
|
||||||
loading = false
|
connected = true
|
||||||
on_connect.emit()
|
on_connect.emit()
|
||||||
|
|
||||||
if packet.event.has("c"):
|
if packet.event.has("c"):
|
||||||
|
@ -201,10 +202,10 @@ func decode_packet(packet: PackedByteArray):
|
||||||
func encode_packet(packet: Dictionary):
|
func encode_packet(packet: Dictionary):
|
||||||
return JSON.stringify(packet)
|
return JSON.stringify(packet)
|
||||||
|
|
||||||
func get_devices():
|
func has_connected():
|
||||||
if loading:
|
return connected
|
||||||
await on_connect
|
|
||||||
|
|
||||||
|
func get_devices():
|
||||||
var result = await send_request_packet({
|
var result = await send_request_packet({
|
||||||
"type": "render_template",
|
"type": "render_template",
|
||||||
"template": devices_template,
|
"template": devices_template,
|
||||||
|
@ -218,18 +219,12 @@ func get_device(id: String):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
func get_state(entity: String):
|
func get_state(entity: String):
|
||||||
if loading:
|
|
||||||
await on_connect
|
|
||||||
|
|
||||||
if entities.has(entity):
|
if entities.has(entity):
|
||||||
return entities[entity]
|
return entities[entity]
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
|
||||||
func watch_state(entity: String, callback: Callable):
|
func watch_state(entity: String, callback: Callable):
|
||||||
if loading:
|
|
||||||
await on_connect
|
|
||||||
|
|
||||||
entitiy_callbacks.add(entity, callback)
|
entitiy_callbacks.add(entity, callback)
|
||||||
|
|
||||||
return func():
|
return func():
|
||||||
|
@ -237,8 +232,6 @@ func watch_state(entity: String, callback: Callable):
|
||||||
|
|
||||||
|
|
||||||
func set_state(entity: String, state: String, attributes: Dictionary = {}):
|
func set_state(entity: String, state: String, attributes: Dictionary = {}):
|
||||||
assert(!loading, "Still loading")
|
|
||||||
|
|
||||||
var domain = entity.split(".")[0]
|
var domain = entity.split(".")[0]
|
||||||
var service: String
|
var service: String
|
||||||
|
|
|
@ -20,7 +20,7 @@ config/icon="res://assets/logo.png"
|
||||||
XRToolsUserSettings="*res://addons/godot-xr-tools/user_settings/user_settings.gd"
|
XRToolsUserSettings="*res://addons/godot-xr-tools/user_settings/user_settings.gd"
|
||||||
ConfigData="*res://lib/globals/config_data.gd"
|
ConfigData="*res://lib/globals/config_data.gd"
|
||||||
Request="*res://lib/globals/request.gd"
|
Request="*res://lib/globals/request.gd"
|
||||||
HomeAdapters="*res://lib/globals/home_adapters.gd"
|
HomeApi="*res://lib/globals/home_api.gd"
|
||||||
AudioPlayer="*res://lib/globals/audio_player.gd"
|
AudioPlayer="*res://lib/globals/audio_player.gd"
|
||||||
EventSystem="*res://lib/globals/event_system.gd"
|
EventSystem="*res://lib/globals/event_system.gd"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user