Finish websocket adapter

This commit is contained in:
Nitwel 2023-11-05 16:36:13 +01:00
parent 93e02391c7
commit 7927d00e5b
11 changed files with 74 additions and 69 deletions

View File

@ -5,7 +5,7 @@ extends StaticBody3D
# Called when the node enters the scene tree for the first time.
func _ready():
var stateInfo = await HomeAdapters.adapter_ws.get_state(entity_id)
var stateInfo = await HomeAdapters.adapter.get_state(entity_id)
if stateInfo["state"] == "on":
sprite.set_frame(0)
else:
@ -13,7 +13,7 @@ func _ready():
func _on_toggle():
HomeAdapters.adapter_ws.set_state(entity_id, "off" if sprite.get_frame() == 0 else "on")
HomeAdapters.adapter.set_state(entity_id, "off" if sprite.get_frame() == 0 else "on")
if sprite.get_frame() == 0:
sprite.set_frame(1)
else:

View File

@ -5,10 +5,10 @@ extends StaticBody3D
# Called when the node enters the scene tree for the first time.
func _ready():
var stateInfo = await HomeAdapters.adapter_ws.get_state(entity_id)
var stateInfo = await HomeAdapters.adapter.get_state(entity_id)
label.text = stateInfo["state"]
await HomeAdapters.adapter_ws.watch_state(entity_id, func(new_state):
await HomeAdapters.adapter.watch_state(entity_id, func(new_state):
label.text = new_state["state"]
)

View File

@ -5,7 +5,7 @@ extends StaticBody3D
# Called when the node enters the scene tree for the first time.
func _ready():
var stateInfo = await HomeAdapters.adapter_ws.get_state(entity_id)
var stateInfo = await HomeAdapters.adapter.get_state(entity_id)
if stateInfo == null:
return
@ -14,7 +14,7 @@ func _ready():
else:
sprite.set_frame(1)
await HomeAdapters.adapter_ws.watch_state(entity_id, func(new_state):
await HomeAdapters.adapter.watch_state(entity_id, func(new_state):
if new_state["state"] == "on":
sprite.set_frame(0)
else:
@ -23,7 +23,7 @@ func _ready():
func _on_toggle():
HomeAdapters.adapter_ws.set_state(entity_id, "off" if sprite.get_frame() == 0 else "on")
HomeAdapters.adapter.set_state(entity_id, "off" if sprite.get_frame() == 0 else "on")
if sprite.get_frame() == 0:
sprite.set_frame(1)
else:

View File

@ -1,13 +1,11 @@
[gd_scene load_steps=13 format=3 uid="uid://eecv28y6jxk4"]
[gd_scene load_steps=11 format=3 uid="uid://eecv28y6jxk4"]
[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://content/raycast.gd" id="1_tsqxc"]
[ext_resource type="Script" path="res://content/main.gd" id="1_uvrd4"]
[ext_resource type="Script" path="res://content/model.gd" id="2_7f1x4"]
[ext_resource type="PackedScene" uid="uid://c3kdssrmv84kv" path="res://content/ui/menu/menu.tscn" id="3_1tbp3"]
[ext_resource type="PackedScene" uid="uid://ctltchlf2j2r4" path="res://addons/xr-simulator/XRSimulator.tscn" id="5_3qc8g"]
[ext_resource type="Material" uid="uid://bf5ina366dwm6" path="res://assets/materials/sky.material" id="5_wgwf8"]
[ext_resource type="PackedScene" uid="uid://cscl5k7lhopj5" path="res://content/entities/switch/switch.tscn" id="8_uxmrb"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_m58yb"]
ao_enabled = true
@ -43,9 +41,6 @@ pose = &"aim"
[node name="MeshInstance3D" type="MeshInstance3D" parent="XROrigin3D/XRControllerLeft"]
mesh = SubResource("BoxMesh_ir3co")
[node name="Model" type="Node3D" parent="XROrigin3D/XRControllerLeft"]
script = ExtResource("2_7f1x4")
[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.183517, 0, -0.0534939)
@ -77,7 +72,3 @@ shadow_enabled = true
[node name="XRSimulator" parent="." instance=ExtResource("5_3qc8g")]
xr_origin = NodePath("../XROrigin3D")
[node name="Switch" parent="." instance=ExtResource("8_uxmrb")]
transform = Transform3D(0.999999, -1.39635e-11, 0, 9.48031e-12, 1, 0, 0, 0, 1, 0.564168, 0.725642, -1.56163)
entity_id = "switch.plug_printer_2_fale"

View File

@ -1,23 +0,0 @@
extends Node3D
@onready var _controller := XRHelpers.get_xr_controller(self)
@export var light: StaticBody3D
# Called when the node enters the scene tree for the first time.
func _ready():
_controller.button_pressed.connect(self._on_button_pressed)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass
func _on_button_pressed(button):
print("right: ", button)
if button != "trigger_click":
return
if light == null:
return
# set light position to controller position
light.transform.origin = _controller.transform.origin

View File

@ -12,7 +12,7 @@ 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()
devices = await HomeAdapters.adapter.get_devices()
render_devices()
func render_devices():

View File

@ -1,11 +1,11 @@
extends Node
var Adapter = preload("res://lib/home_adapters/adapter.gd")
const Adapter = preload("res://lib/home_adapters/adapter.gd")
var adapter = Adapter.new(Adapter.ADAPTER_TYPES.HASS)
var adapter_ws = Adapter.new(Adapter.ADAPTER_TYPES.HASS_WS)
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_ws)
# add_child(adapter_http)

View File

@ -1,7 +1,7 @@
extends Node
const hass = preload("res://lib/home_adapters/hass/hass.gd")
const hass_ws = preload("res://lib/home_adapters/hass_ws/hass.gd")
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,
@ -9,14 +9,16 @@ enum ADAPTER_TYPES {
}
const adapters = {
ADAPTER_TYPES.HASS: hass,
ADAPTER_TYPES.HASS_WS: hass_ws
ADAPTER_TYPES.HASS: Hass,
ADAPTER_TYPES.HASS_WS: HassWebSocket
}
const methods = [
"load_devices",
"get_devices",
"get_device",
"get_state",
"set_state"
"set_state",
"watch_state"
]
var adapter: Node
@ -27,15 +29,23 @@ func _init(type: ADAPTER_TYPES):
for method in methods:
assert(adapter.has_method(method), "Adapter does not implement method: " + method)
func load_devices():
return await adapter.load_devices()
## 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)

View File

@ -13,7 +13,7 @@ func _init(url := self.url, token := self.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():
func get_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("'", "\"")

View File

@ -1,13 +1,13 @@
extends Node
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_adapters/hass_ws/templates/devices.j2")
var socket := WebSocketPeer.new()
# in seconds
var request_timeout := 10.0
var url := "ws://192.168.33.33:8123/api/websocket"
var token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzZjQ0ZGM2N2Y3YzY0MDc1OGZlMWI2ZjJlNmIxZjRkNSIsImlhdCI6MTY5ODAxMDcyOCwiZXhwIjoyMDEzMzcwNzI4fQ.K6ydLUC-4Q7BNIRCU1nWlI2s6sg9UCiOu-Lpedw2zJc"
var LOG_MESSAGES := false
var LOG_MESSAGES := true
var authenticated := false
var loading := true
@ -24,7 +24,7 @@ func _init(url := self.url, token := self.token):
self.url = url
self.token = token
devices_template = devices_template.replace("\n", " ").replace("\t", "").replace("\r", " ").replace("\"", "\\\"")
devices_template = devices_template.replace("\n", " ").replace("\t", "").replace("\r", " ")
connect_ws()
func connect_ws():
@ -56,7 +56,7 @@ func _process(delta):
handle_disconnect()
func handle_packet(packet: Dictionary):
if LOG_MESSAGES: print("Received packet: %s" % packet)
if LOG_MESSAGES: print("Received packet: %s" % str(packet).substr(0, 1000))
if packet.type == "auth_required":
send_packet({
@ -139,21 +139,34 @@ func send_subscribe_packet(packet: Dictionary, callback: Callable):
id += 1
func send_request_packet(packet: Dictionary):
func send_request_packet(packet: Dictionary, ignore_initial := false):
packet.id = id
id += 1
send_packet(packet)
var promise = Promise.new(func(resolve: Callable, reject: Callable):
packet_callbacks.add_once(packet.id, resolve)
var promise = Promise.new(func(resolve: Callable, reject: Callable):
var fn: Callable
if ignore_initial:
fn = func(packet: Dictionary):
if packet.type == "event":
resolve.call(packet)
packet_callbacks.remove(packet.id, fn)
packet_callbacks.add(packet.id, fn)
else:
packet_callbacks.add_once(packet.id, resolve)
var timeout = Timer.new()
timeout.set_wait_time(request_timeout)
timeout.set_one_shot(true)
timeout.timeout.connect(func():
reject.call(Promise.Rejection.new("Request timed out"))
packet_callbacks.remove(packet.id, resolve)
if ignore_initial:
packet_callbacks.remove(packet.id, fn)
else:
packet_callbacks.remove(packet.id, resolve)
)
add_child(timeout)
timeout.start()
@ -163,7 +176,7 @@ func send_request_packet(packet: Dictionary):
func send_packet(packet: Dictionary):
if LOG_MESSAGES || true: print("Sending packet: %s" % encode_packet(packet))
if LOG_MESSAGES: print("Sending packet: %s" % encode_packet(packet))
socket.send_text(encode_packet(packet))
func decode_packet(packet: PackedByteArray):
@ -172,11 +185,21 @@ func decode_packet(packet: PackedByteArray):
func encode_packet(packet: Dictionary):
return JSON.stringify(packet)
func load_devices():
func get_devices():
if loading:
await on_connect
return entities
var result = await send_request_packet({
"type": "render_template",
"template": devices_template,
"timeout": 3,
"report_errors": true
}, true)
return result.payload.event.result
func get_device(id: String):
pass
func get_state(entity: String):
if loading:
@ -193,6 +216,9 @@ func watch_state(entity: String, callback: Callable):
entitiy_callbacks.add(entity, callback)
return func():
entitiy_callbacks.remove(entity, callback)
func set_state(entity: String, state: String, attributes: Dictionary = {}):
assert(!loading, "Still loading")
@ -211,6 +237,9 @@ func set_state(entity: String, state: String, attributes: Dictionary = {}):
elif state == 'off':
service = 'turn_off'
if service == null:
return null
return await send_request_packet({
"type": "call_service",
"domain": domain,

View File

@ -7,6 +7,4 @@
{%- set ns.devices = ns.devices + [ {device: {"name": device_attr(device, "name"), "entities": entities }} ] %}
{%- endif %}
{%- endfor %}
{
"data": {{ ns.devices }}
}
{{ ns.devices }}