finally fix websockets and add sensor entity
This commit is contained in:
parent
3d411188a6
commit
f3f0c93547
15
scenes/entities/sensor.tscn
Normal file
15
scenes/entities/sensor.tscn
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[gd_scene load_steps=3 format=3 uid="uid://xsiy71rsqulj"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://src/entities/sensor.gd" id="1_57ac8"]
|
||||||
|
|
||||||
|
[sub_resource type="SphereShape3D" id="SphereShape3D_r20gc"]
|
||||||
|
radius = 0.1
|
||||||
|
|
||||||
|
[node name="Sensor" type="StaticBody3D"]
|
||||||
|
script = ExtResource("1_57ac8")
|
||||||
|
|
||||||
|
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||||
|
shape = SubResource("SphereShape3D_r20gc")
|
||||||
|
|
||||||
|
[node name="Label" type="Label3D" parent="."]
|
||||||
|
text = "some text"
|
16
src/entities/sensor.gd
Normal file
16
src/entities/sensor.gd
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
extends StaticBody3D
|
||||||
|
|
||||||
|
@export var entity_id = "sensor.sun_next_dawn"
|
||||||
|
@onready var label: Label3D = $Label
|
||||||
|
|
||||||
|
# Called when the node enters the scene tree for the first time.
|
||||||
|
func _ready():
|
||||||
|
var stateInfo = await HomeAdapters.adapter_ws.get_state(entity_id)
|
||||||
|
label.text = stateInfo["state"]
|
||||||
|
|
||||||
|
await HomeAdapters.adapter_ws.watch_state(entity_id, func(new_state):
|
||||||
|
label.text = new_state["state"]
|
||||||
|
)
|
||||||
|
|
||||||
|
func _on_toggle():
|
||||||
|
pass
|
|
@ -11,6 +11,13 @@ func _ready():
|
||||||
else:
|
else:
|
||||||
sprite.set_frame(1)
|
sprite.set_frame(1)
|
||||||
|
|
||||||
|
await HomeAdapters.adapter_ws.watch_state(entity_id, func(new_state):
|
||||||
|
if new_state["state"] == "on":
|
||||||
|
sprite.set_frame(0)
|
||||||
|
else:
|
||||||
|
sprite.set_frame(1)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
func _on_toggle():
|
func _on_toggle():
|
||||||
HomeAdapters.adapter_ws.set_state(entity_id, "off" if sprite.get_frame() == 0 else "on")
|
HomeAdapters.adapter_ws.set_state(entity_id, "off" if sprite.get_frame() == 0 else "on")
|
||||||
|
|
|
@ -7,7 +7,7 @@ var request_timeout := 10.0
|
||||||
|
|
||||||
var url := "ws://192.168.33.33:8123/api/websocket"
|
var url := "ws://192.168.33.33:8123/api/websocket"
|
||||||
var token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzZjQ0ZGM2N2Y3YzY0MDc1OGZlMWI2ZjJlNmIxZjRkNSIsImlhdCI6MTY5ODAxMDcyOCwiZXhwIjoyMDEzMzcwNzI4fQ.K6ydLUC-4Q7BNIRCU1nWlI2s6sg9UCiOu-Lpedw2zJc"
|
var token := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzZjQ0ZGM2N2Y3YzY0MDc1OGZlMWI2ZjJlNmIxZjRkNSIsImlhdCI6MTY5ODAxMDcyOCwiZXhwIjoyMDEzMzcwNzI4fQ.K6ydLUC-4Q7BNIRCU1nWlI2s6sg9UCiOu-Lpedw2zJc"
|
||||||
|
var LOG_MESSAGES := false
|
||||||
|
|
||||||
var authenticated := false
|
var authenticated := false
|
||||||
var id := 1
|
var id := 1
|
||||||
|
@ -30,14 +30,22 @@ func connect_ws():
|
||||||
print("Connecting to %s" % self.url)
|
print("Connecting to %s" % self.url)
|
||||||
socket.connect_to_url(self.url)
|
socket.connect_to_url(self.url)
|
||||||
|
|
||||||
|
# https://github.com/godotengine/godot/issues/84423
|
||||||
|
# Otherwise the WebSocketPeer will crash when receiving large packets
|
||||||
|
socket.set_inbound_buffer_size(65535 * 2)
|
||||||
|
|
||||||
func _process(delta):
|
func _process(delta):
|
||||||
socket.poll()
|
socket.poll()
|
||||||
|
|
||||||
var state = socket.get_ready_state()
|
var state = socket.get_ready_state()
|
||||||
print(state, "POLLING")
|
|
||||||
if state == WebSocketPeer.STATE_OPEN:
|
if state == WebSocketPeer.STATE_OPEN:
|
||||||
while socket.get_available_packet_count():
|
while socket.get_available_packet_count():
|
||||||
handle_packet(socket.get_packet())
|
var packet = decode_packet(socket.get_packet())
|
||||||
|
if typeof(packet) == TYPE_DICTIONARY:
|
||||||
|
handle_packet(packet)
|
||||||
|
elif typeof(packet) == TYPE_ARRAY:
|
||||||
|
for p in packet:
|
||||||
|
handle_packet(p)
|
||||||
elif state == WebSocketPeer.STATE_CLOSING:
|
elif state == WebSocketPeer.STATE_CLOSING:
|
||||||
pass
|
pass
|
||||||
elif state == WebSocketPeer.STATE_CLOSED:
|
elif state == WebSocketPeer.STATE_CLOSED:
|
||||||
|
@ -46,10 +54,8 @@ func _process(delta):
|
||||||
print("WS connection closed with code: %s, reason: %s" % [code, reason])
|
print("WS connection closed with code: %s, reason: %s" % [code, reason])
|
||||||
handle_disconnect()
|
handle_disconnect()
|
||||||
|
|
||||||
func handle_packet(raw_packet: PackedByteArray):
|
func handle_packet(packet: Dictionary):
|
||||||
var packet = decode_packet(raw_packet)
|
if LOG_MESSAGES: print("Received packet: %s" % packet)
|
||||||
|
|
||||||
print("Received packet: %s" % packet)
|
|
||||||
|
|
||||||
if packet.type == "auth_required":
|
if packet.type == "auth_required":
|
||||||
send_packet({
|
send_packet({
|
||||||
|
@ -64,17 +70,22 @@ func handle_packet(raw_packet: PackedByteArray):
|
||||||
elif packet.type == "auth_invalid":
|
elif packet.type == "auth_invalid":
|
||||||
handle_disconnect()
|
handle_disconnect()
|
||||||
else:
|
else:
|
||||||
packet_callbacks.call_key(packet.id, [packet])
|
packet_callbacks.call_key(int(packet.id), [packet])
|
||||||
|
|
||||||
func start_subscriptions():
|
func start_subscriptions():
|
||||||
assert(authenticated, "Not authenticated")
|
assert(authenticated, "Not authenticated")
|
||||||
|
|
||||||
await send_request_packet({
|
# await send_request_packet({
|
||||||
"type": "supported_features",
|
# "type": "supported_features",
|
||||||
"features": {
|
# "features": {
|
||||||
"coalesce_messages": 1
|
# "coalesce_messages": 1
|
||||||
}
|
# }
|
||||||
})
|
# })
|
||||||
|
|
||||||
|
# await send_request_packet({
|
||||||
|
# "type": "subscribe_events",
|
||||||
|
# "event_type": "state_changed"
|
||||||
|
# })
|
||||||
|
|
||||||
send_subscribe_packet({
|
send_subscribe_packet({
|
||||||
"type": "subscribe_entities"
|
"type": "subscribe_entities"
|
||||||
|
@ -84,14 +95,23 @@ func start_subscriptions():
|
||||||
|
|
||||||
if packet.event.has("a"):
|
if packet.event.has("a"):
|
||||||
for entity in packet.event.a.keys():
|
for entity in packet.event.a.keys():
|
||||||
entities[entity] = packet.event.a[entity]
|
entities[entity] = {
|
||||||
|
"state": packet.event.a[entity]["s"],
|
||||||
|
"attributes": packet.event.a[entity]["a"]
|
||||||
|
}
|
||||||
entitiy_callbacks.call_key(entity, [entities[entity]])
|
entitiy_callbacks.call_key(entity, [entities[entity]])
|
||||||
on_connect.emit()
|
on_connect.emit()
|
||||||
|
|
||||||
if packet.event.has("c"):
|
if packet.event.has("c"):
|
||||||
for entity in packet.event.c.keys():
|
for entity in packet.event.c.keys():
|
||||||
|
if !entities.has(entity):
|
||||||
|
continue
|
||||||
|
|
||||||
if packet.event.c[entity].has("+"):
|
if packet.event.c[entity].has("+"):
|
||||||
entities[entity].merge(packet.event.c[entity]["+"])
|
if packet.event.c[entity]["+"].has("s"):
|
||||||
|
entities[entity]["state"] = packet.event.c[entity]["+"]["s"]
|
||||||
|
if packet.event.c[entity]["+"].has("a"):
|
||||||
|
entities[entity]["attributes"].merge(packet.event.c[entity]["+"]["a"])
|
||||||
entitiy_callbacks.call_key(entity, [entities[entity]])
|
entitiy_callbacks.call_key(entity, [entities[entity]])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -104,8 +124,8 @@ func send_subscribe_packet(packet: Dictionary, callback: Callable):
|
||||||
packet.id = id
|
packet.id = id
|
||||||
id += 1
|
id += 1
|
||||||
|
|
||||||
send_packet(packet)
|
|
||||||
packet_callbacks.add(packet.id, callback)
|
packet_callbacks.add(packet.id, callback)
|
||||||
|
send_packet(packet)
|
||||||
|
|
||||||
return func():
|
return func():
|
||||||
packet_callbacks.remove(packet.id, callback)
|
packet_callbacks.remove(packet.id, callback)
|
||||||
|
@ -141,7 +161,7 @@ func send_request_packet(packet: Dictionary):
|
||||||
|
|
||||||
|
|
||||||
func send_packet(packet: Dictionary):
|
func send_packet(packet: Dictionary):
|
||||||
print("Sending packet: %s" % encode_packet(packet))
|
if LOG_MESSAGES || true: print("Sending packet: %s" % encode_packet(packet))
|
||||||
socket.send_text(encode_packet(packet))
|
socket.send_text(encode_packet(packet))
|
||||||
|
|
||||||
func decode_packet(packet: PackedByteArray):
|
func decode_packet(packet: PackedByteArray):
|
||||||
|
@ -151,7 +171,10 @@ func encode_packet(packet: Dictionary):
|
||||||
return JSON.stringify(packet)
|
return JSON.stringify(packet)
|
||||||
|
|
||||||
func load_devices():
|
func load_devices():
|
||||||
pass
|
if !authenticated:
|
||||||
|
await on_connect
|
||||||
|
|
||||||
|
return entities
|
||||||
|
|
||||||
func get_state(entity: String):
|
func get_state(entity: String):
|
||||||
if !authenticated:
|
if !authenticated:
|
||||||
|
@ -159,8 +182,7 @@ func get_state(entity: String):
|
||||||
|
|
||||||
if entities.has(entity):
|
if entities.has(entity):
|
||||||
return entities[entity]
|
return entities[entity]
|
||||||
else:
|
return null
|
||||||
print(entities, entity)
|
|
||||||
|
|
||||||
|
|
||||||
func watch_state(entity: String, callback: Callable):
|
func watch_state(entity: String, callback: Callable):
|
||||||
|
@ -174,7 +196,18 @@ func set_state(entity: String, state: String, attributes: Dictionary = {}):
|
||||||
assert(authenticated, "Not authenticated")
|
assert(authenticated, "Not authenticated")
|
||||||
|
|
||||||
var domain = entity.split(".")[0]
|
var domain = entity.split(".")[0]
|
||||||
var service = entity.split(".")[1]
|
var service: String
|
||||||
|
|
||||||
|
if domain == 'switch':
|
||||||
|
if state == 'on':
|
||||||
|
service = 'turn_on'
|
||||||
|
elif state == 'off':
|
||||||
|
service = 'turn_off'
|
||||||
|
elif domain == 'light':
|
||||||
|
if state == 'on':
|
||||||
|
service = 'turn_on'
|
||||||
|
elif state == 'off':
|
||||||
|
service = 'turn_off'
|
||||||
|
|
||||||
return await send_request_packet({
|
return await send_request_packet({
|
||||||
"type": "call_service",
|
"type": "call_service",
|
||||||
|
|
|
@ -4,6 +4,7 @@ const Device = preload("res://scenes/device.tscn")
|
||||||
const Entity = preload("res://scenes/entity.tscn")
|
const Entity = preload("res://scenes/entity.tscn")
|
||||||
const Switch = preload("res://scenes/entities/switch.tscn")
|
const Switch = preload("res://scenes/entities/switch.tscn")
|
||||||
const Light = preload("res://scenes/entities/light.tscn")
|
const Light = preload("res://scenes/entities/light.tscn")
|
||||||
|
const Sensor = preload("res://scenes/entities/sensor.tscn")
|
||||||
|
|
||||||
@onready var devices_node = $Devices
|
@onready var devices_node = $Devices
|
||||||
var devices
|
var devices
|
||||||
|
@ -93,6 +94,13 @@ func _on_entity_click(entity_name):
|
||||||
|
|
||||||
light.set_position(global_position)
|
light.set_position(global_position)
|
||||||
get_node("/root").add_child(light)
|
get_node("/root").add_child(light)
|
||||||
|
|
||||||
|
if type == "sensor":
|
||||||
|
var sensor = Sensor.instantiate()
|
||||||
|
sensor.entity_id = entity_name
|
||||||
|
|
||||||
|
sensor.set_position(global_position)
|
||||||
|
get_node("/root").add_child(sensor)
|
||||||
|
|
||||||
func clear_menu():
|
func clear_menu():
|
||||||
for child in devices_node.get_children():
|
for child in devices_node.get_children():
|
||||||
|
|
Loading…
Reference in New Issue
Block a user