2023-11-03 00:13:55 +02:00
|
|
|
extends Node
|
|
|
|
|
2024-03-11 19:09:50 +02:00
|
|
|
const IntegrationHandler = preload ("./handlers/integration.gd")
|
2024-03-15 01:13:05 +02:00
|
|
|
const AssistHandler = preload ("./handlers/assist.gd")
|
2024-04-11 17:51:30 +03:00
|
|
|
const HistoryHandler = preload ("./handlers/history.gd")
|
2024-05-20 13:53:22 +03:00
|
|
|
const Connection = preload ("./connection.gd")
|
2024-03-11 19:09:50 +02:00
|
|
|
|
2023-11-24 02:36:31 +02:00
|
|
|
signal on_connect()
|
|
|
|
signal on_disconnect()
|
|
|
|
|
|
|
|
var devices_template := FileAccess.get_file_as_string("res://lib/home_apis/hass_ws/templates/devices.j2")
|
2023-11-03 00:13:55 +02:00
|
|
|
|
2023-11-03 03:07:53 +02:00
|
|
|
var entities: Dictionary = {}
|
|
|
|
var entitiy_callbacks := CallbackMap.new()
|
|
|
|
|
2024-05-20 13:53:22 +03:00
|
|
|
var connection: Connection
|
2024-03-11 19:09:50 +02:00
|
|
|
var integration_handler: IntegrationHandler
|
2024-03-15 01:13:05 +02:00
|
|
|
var assist_handler: AssistHandler
|
2024-04-11 17:51:30 +03:00
|
|
|
var history_handler: HistoryHandler
|
2024-03-11 19:09:50 +02:00
|
|
|
|
2024-05-20 13:53:22 +03:00
|
|
|
func _init(url: String, token: String):
|
|
|
|
connection = Connection.new(self)
|
|
|
|
add_child(connection)
|
2023-11-03 00:13:55 +02:00
|
|
|
|
2024-05-20 13:53:22 +03:00
|
|
|
connection.on_disconnect.connect(func():
|
|
|
|
on_disconnect.emit()
|
2024-03-11 19:09:50 +02:00
|
|
|
)
|
|
|
|
|
2024-05-20 13:53:22 +03:00
|
|
|
var error = await connection.start(url, token)
|
2023-12-13 23:22:52 +02:00
|
|
|
|
2024-05-20 13:53:22 +03:00
|
|
|
if error != Connection.ConnectionError.OK:
|
|
|
|
print("Error starting connection: ", error)
|
|
|
|
return
|
2023-11-03 00:13:55 +02:00
|
|
|
|
2024-05-20 13:53:22 +03:00
|
|
|
integration_handler = IntegrationHandler.new(self)
|
|
|
|
assist_handler = AssistHandler.new(self)
|
|
|
|
history_handler = HistoryHandler.new(self)
|
2023-11-03 00:13:55 +02:00
|
|
|
|
2024-05-20 13:53:22 +03:00
|
|
|
start_subscriptions()
|
2023-11-03 00:13:55 +02:00
|
|
|
|
2024-05-20 13:53:22 +03:00
|
|
|
devices_template = devices_template.replace("\n", " ").replace("\t", "").replace("\r", " ")
|
2023-11-03 03:07:53 +02:00
|
|
|
|
|
|
|
func start_subscriptions():
|
2024-05-20 13:53:22 +03:00
|
|
|
connection.send_subscribe_packet({
|
2023-11-03 03:07:53 +02:00
|
|
|
"type": "subscribe_entities"
|
|
|
|
}, func(packet: Dictionary):
|
|
|
|
if packet.type != "event":
|
|
|
|
return
|
|
|
|
|
|
|
|
if packet.event.has("a"):
|
|
|
|
for entity in packet.event.a.keys():
|
2024-03-11 19:09:50 +02:00
|
|
|
entities[entity]={
|
2023-11-03 23:00:05 +02:00
|
|
|
"state": packet.event.a[entity]["s"],
|
|
|
|
"attributes": packet.event.a[entity]["a"]
|
|
|
|
}
|
2023-11-03 03:07:53 +02:00
|
|
|
entitiy_callbacks.call_key(entity, [entities[entity]])
|
2024-05-20 13:53:22 +03:00
|
|
|
on_connect.emit()
|
2023-11-03 03:07:53 +02:00
|
|
|
|
|
|
|
if packet.event.has("c"):
|
|
|
|
for entity in packet.event.c.keys():
|
2023-11-03 23:00:05 +02:00
|
|
|
if !entities.has(entity):
|
|
|
|
continue
|
|
|
|
|
2023-11-03 03:07:53 +02:00
|
|
|
if packet.event.c[entity].has("+"):
|
2023-11-03 23:00:05 +02:00
|
|
|
if packet.event.c[entity]["+"].has("s"):
|
2024-03-11 19:09:50 +02:00
|
|
|
entities[entity]["state"]=packet.event.c[entity]["+"]["s"]
|
2023-11-03 23:00:05 +02:00
|
|
|
if packet.event.c[entity]["+"].has("a"):
|
2023-11-12 18:36:23 +02:00
|
|
|
entities[entity]["attributes"].merge(packet.event.c[entity]["+"]["a"], true)
|
2023-11-03 03:07:53 +02:00
|
|
|
entitiy_callbacks.call_key(entity, [entities[entity]])
|
|
|
|
)
|
|
|
|
|
2023-11-24 02:36:31 +02:00
|
|
|
func has_connected():
|
2024-05-20 13:53:22 +03:00
|
|
|
return connection.connected
|
2023-11-03 23:00:05 +02:00
|
|
|
|
2023-11-24 02:36:31 +02:00
|
|
|
func get_devices():
|
2024-05-20 13:53:22 +03:00
|
|
|
var result = await connection.send_request_packet({
|
2023-11-05 17:36:13 +02:00
|
|
|
"type": "render_template",
|
|
|
|
"template": devices_template,
|
|
|
|
"timeout": 3,
|
|
|
|
"report_errors": true
|
|
|
|
}, true)
|
|
|
|
|
|
|
|
return result.payload.event.result
|
|
|
|
|
|
|
|
func get_device(id: String):
|
|
|
|
pass
|
2023-11-03 00:13:55 +02:00
|
|
|
|
|
|
|
func get_state(entity: String):
|
2023-11-03 03:07:53 +02:00
|
|
|
if entities.has(entity):
|
|
|
|
return entities[entity]
|
2023-11-03 23:00:05 +02:00
|
|
|
return null
|
2023-11-03 00:13:55 +02:00
|
|
|
|
|
|
|
func watch_state(entity: String, callback: Callable):
|
2023-11-03 03:07:53 +02:00
|
|
|
entitiy_callbacks.add(entity, callback)
|
2023-11-03 00:13:55 +02:00
|
|
|
|
2023-11-05 17:36:13 +02:00
|
|
|
return func():
|
|
|
|
entitiy_callbacks.remove(entity, callback)
|
|
|
|
|
2024-03-12 15:51:09 +02:00
|
|
|
func set_state(entity: String, state: Variant, attributes: Dictionary={}):
|
2023-11-03 03:07:53 +02:00
|
|
|
var domain = entity.split(".")[0]
|
2023-11-03 23:00:05 +02:00
|
|
|
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'
|
2023-11-26 03:01:27 +02:00
|
|
|
elif domain == 'media_player':
|
|
|
|
if state == 'play':
|
|
|
|
service = 'media_play'
|
|
|
|
elif state == "pause":
|
|
|
|
service = "media_pause"
|
|
|
|
elif state == "next":
|
|
|
|
service = "media_next_track"
|
|
|
|
elif state == "previous":
|
|
|
|
service = "media_previous_track"
|
2023-11-29 01:47:11 +02:00
|
|
|
elif state == "volume":
|
|
|
|
service = "volume_set"
|
2023-12-10 01:34:54 +02:00
|
|
|
elif domain == 'button':
|
|
|
|
if state == 'pressed':
|
|
|
|
service = 'press'
|
2024-03-12 15:51:09 +02:00
|
|
|
elif domain == 'number':
|
|
|
|
service = 'set_value'
|
|
|
|
attributes["value"] = state
|
2024-05-01 20:08:09 +03:00
|
|
|
elif domain == 'timer':
|
|
|
|
if state == 'start':
|
|
|
|
service = 'start'
|
|
|
|
elif state == 'cancel':
|
|
|
|
service = 'cancel'
|
|
|
|
elif state == 'pause':
|
|
|
|
service = 'pause'
|
2023-11-03 03:07:53 +02:00
|
|
|
|
2023-11-05 17:36:13 +02:00
|
|
|
if service == null:
|
|
|
|
return null
|
|
|
|
|
2024-05-20 13:53:22 +03:00
|
|
|
return await connection.send_request_packet({
|
2023-11-03 03:07:53 +02:00
|
|
|
"type": "call_service",
|
|
|
|
"domain": domain,
|
|
|
|
"service": service,
|
|
|
|
"service_data": attributes,
|
|
|
|
"target": {
|
|
|
|
"entity_id": entity
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2024-03-12 13:49:17 +02:00
|
|
|
func has_integration():
|
|
|
|
return integration_handler.integration_exists
|
|
|
|
|
2024-03-11 19:09:50 +02:00
|
|
|
func update_room(room: String):
|
2024-05-20 13:53:22 +03:00
|
|
|
var response = await connection.send_request_packet({
|
2024-03-11 19:09:50 +02:00
|
|
|
"type": "immersive_home/update",
|
|
|
|
"device_id": OS.get_unique_id(),
|
|
|
|
"room": room
|
|
|
|
})
|
|
|
|
|
|
|
|
if response.status == Promise.Status.RESOLVED:
|
2024-03-17 18:05:45 +02:00
|
|
|
pass
|
|
|
|
|
|
|
|
func get_voice_assistant():
|
|
|
|
return assist_handler
|
2024-04-11 17:51:30 +03:00
|
|
|
|
2024-05-27 18:22:20 +03:00
|
|
|
func get_history(entity_id, start, interval, end=null):
|
|
|
|
return await history_handler.get_history(entity_id, start, interval, end)
|