Skip to content

[FP2] apply necessary modifications and improvements #2058

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Apr 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions drivers/Aqara/aqara-presence-sensor/src/discovery.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ function discovery.set_device_field(driver, device)
driver.datastore.discovery_cache[device.device_network_id] = nil
end

local function update_device_discovery_cache(driver, dni, ip)
local device_info = driver.discovery_helper.get_device_info(driver, dni, ip)
local function update_device_discovery_cache(driver, dni, ip, device_info)
if driver.datastore.discovery_cache[dni] == nil then
driver.datastore.discovery_cache[dni] = {}
end
Expand All @@ -33,9 +32,10 @@ end

local function try_add_device(driver, device_dni, device_ip)
log.trace(string.format("try_add_device : dni= %s, ip= %s", device_dni, device_ip))
local device_info = driver.discovery_helper.get_device_info(driver, device_dni, device_ip)

update_device_discovery_cache(driver, device_dni, device_ip)
local create_device_msg = driver.discovery_helper.get_device_create_msg(driver, device_dni, device_ip)
update_device_discovery_cache(driver, device_dni, device_ip, device_info)
local create_device_msg = driver.discovery_helper.get_device_create_msg(driver, device_dni, device_ip, device_info)

local credential = driver.discovery_helper.get_credential(driver, device_dni, device_ip)

Expand Down Expand Up @@ -93,7 +93,14 @@ local function discovery_device(driver)

for dni, ip in pairs(unknown_discovered_devices) do
log.trace(string.format("unknown dni= %s, ip= %s", dni, ip))
if not processing_devices[dni] then
local is_already_added = false
for _, device in pairs(driver:get_devices()) do
if device.device_network_id == dni then
is_already_added = true
break
end
end
if (not processing_devices[dni]) and (not is_already_added) then
try_add_device(driver, dni, ip)
end
end
Expand Down
3 changes: 2 additions & 1 deletion drivers/Aqara/aqara-presence-sensor/src/fields.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ local fields = {
EVENT_SOURCE = "eventsource",
MONITORING_TIMER = "monitoring_timer",
CREDENTIAL = "credential",
_INIT = "init"
_INIT = "init",
CONNECTION_STATUS = "connection_status"
}

return fields
12 changes: 7 additions & 5 deletions drivers/Aqara/aqara-presence-sensor/src/fp2/discovery_helper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ function discovery_helper.get_service_type_and_domain()
return SERVICE_TYPE, DOMAIN
end

function discovery_helper.get_device_create_msg(driver, device_dni, device_ip)
local device_info = fp2_api.get_info(device_ip, fp2_api.labeled_socket_builder(device_dni))

function discovery_helper.get_device_create_msg(driver, device_dni, device_ip, device_info)
if not device_info then
log.warn("failed to create device create msg. device_info is nil.")
return nil
device_info = fp2_api.get_info(device_ip, fp2_api.labeled_socket_builder(device_dni))

if not device_info then
log.warn("failed to create device create msg. device_info is nil.")
return nil
end
end

local device_label = device_info.label or "Aqara-FP2"
Expand Down
52 changes: 48 additions & 4 deletions drivers/Aqara/aqara-presence-sensor/src/init.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local log = require "log"
local socket = require "cosock.socket"
local capabilities = require "st.capabilities"
local Driver = require "st.driver"
local discovery = require "discovery"
Expand Down Expand Up @@ -54,13 +55,22 @@ local function create_sse(driver, device, credential)
end

eventsource.onerror = function()
log.error(string.format("Eventsource error: dni= %s", device.device_network_id))
local DISCONNECTED_STATUS = "disconnected"
local connection_status = device:get_field(fields.CONNECTION_STATUS)
if connection_status and connection_status == DISCONNECTED_STATUS then
log.error(string.format("Eventsource error: dni= %s", device.device_network_id))
else
log.error_with({ hub_logs = true }, string.format("Eventsource error: disconnected, dni= %s", device.device_network_id))
device:set_field(fields.CONNECTION_STATUS, DISCONNECTED_STATUS)
end
device:offline()

end

eventsource.onopen = function()
log.info_with({ hub_logs = true }, string.format("Eventsource open: dni= %s", device.device_network_id))
device:online()
device:set_field(fields.CONNECTION_STATUS, "connected")
local success, err = status_update(driver, device)
if not success then
log.warn(string.format("Failed to status_update during eventsource.onopen, err = %s dni= %s", err, device.device_network_id))
Expand Down Expand Up @@ -125,7 +135,6 @@ local function create_monitoring_thread(driver, device, device_info)
local monitoring_interval = DEFAULT_MONITORING_INTERVAL
local new_timer = device.thread:call_on_schedule(monitoring_interval, function()
check_and_update_connection(driver, device)
driver.device_manager.device_monitor(driver, device, device_info)
end, "monitor_timer")
device:set_field(fields.MONITORING_TIMER, new_timer)
end
Expand All @@ -145,22 +154,27 @@ end

local function device_removed(driver, device)
local conn_info = device:get_field(fields.CONN_INFO)
driver.removing_devices = driver.removing_devices + 1
log.info_with({ hub_logs = true }, string.format("Device removed: dni= %s", device.device_network_id))
if not conn_info then
log.warn(string.format("remove : failed to find conn_info, dni = %s", device.device_network_id))
log.warn_with({ hub_logs = true }, string.format("remove : failed to find conn_info, dni = %s", device.device_network_id))
else
local _, err, status = conn_info:get_remove()

if err or status ~= 200 then
log.error(string.format("remove : failed to get remove, dni= %s, err= %s, status= %s", device.device_network_id,
log.error_with({ hub_logs = true }, string.format("remove : failed to get remove, dni= %s, err= %s, status= %s", device.device_network_id,
err,
status))
else
log.info_with({ hub_logs = true }, string.format("Device removed: token reset success. dni= %s", device.device_network_id))
end
end

local eventsource = device:get_field(fields.EVENT_SOURCE)
if eventsource then
eventsource:close()
end
driver.removing_devices = driver.removing_devices - 1
end

local function device_init(driver, device)
Expand Down Expand Up @@ -194,13 +208,41 @@ local function device_init(driver, device)

update_connection(driver, device, device_ip, device_info)

local eventsource = device:get_field(fields.EVENT_SOURCE)
if not eventsource then
log.error_with({ hub_logs = true }, "failed to create EVENT_SOURCE.")
device:offline()
return
end

do_refresh(driver, device, nil)
end

local function device_info_changed(driver, device, event, args)
do_refresh(driver, device, nil)
end

local function driver_lifecycle_handler(driver, event_name)
log.info(string.format("driver lifecycle event :'%s'", event_name))
if event_name == "shutdown" then
local MAXIMUM_WAITING_TIME = 30
local WAITING_TIME = 1
local total_waiting_time = 0

while (driver.removing_devices > 0) do
log.info("waiting for all devices to be removed")
total_waiting_time = total_waiting_time + WAITING_TIME
socket.sleep(WAITING_TIME) -- wait for 1 seconds

if total_waiting_time > MAXIMUM_WAITING_TIME then
log.error_with({ hub_logs = true }, "maximum waiting time exceeded")
end
end
log.info(string.format("forced exit"))
os.exit(0)
end
end

local lan_driver = Driver("aqara-fp2",
{
discovery = discovery.do_network_discovery,
Expand All @@ -210,6 +252,7 @@ local lan_driver = Driver("aqara-fp2",
infoChanged = device_info_changed,
removed = device_removed
},
driver_lifecycle = driver_lifecycle_handler,
capability_handlers = {
[capabilities.refresh.ID] = {
[capabilities.refresh.commands.refresh.NAME] = do_refresh,
Expand All @@ -221,6 +264,7 @@ local lan_driver = Driver("aqara-fp2",
discovery_helper = fp2_discovery_helper,
device_manager = fp2_device_manager,
controlled_devices = {},
removing_devices = 0
}
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ local util = require "lunchbox.util"
local Request = require "luncheon.request"
local Response = require "luncheon.response"

local MAX_RECONNECT_TIME_SEC = 60

--- A pure Lua implementation of the EventSource interface.
--- The EventSource interface represents the client end of an HTTP(S)
--- connection that receives an event stream following the Server-Sent events
Expand Down Expand Up @@ -302,6 +304,11 @@ local function connecting_action(source)
return nil, err or "nil response from Response.tcp_source"
end

if response.status == 401 then
source._reconnect = false
return nil, "Server response is 401 Unauthorized, stop reconnect", { response.status, response.status_msg }
end

if response.status ~= 200 then
return nil, "Server responded with status other than 200 OK", { response.status, response.status_msg }
end
Expand All @@ -317,6 +324,8 @@ local function connecting_action(source)
end

source.ready_state = EventSource.ReadyStates.OPEN
source._reconnect = true
source._reconnect_time_millis = 1000

if type(source.onopen) == "function" then
source.onopen()
Expand Down Expand Up @@ -418,7 +427,9 @@ local function closed_action(source)

local sleep_time_secs = source._reconnect_time_millis / 1000.0
socket.sleep(sleep_time_secs)

if source._reconnect_time_millis <= MAX_RECONNECT_TIME_SEC * 1000 then
source._reconnect_time_millis = source._reconnect_time_millis + 1000.0
end
source.ready_state = EventSource.ReadyStates.CONNECTING
end
end
Expand Down
Loading