diff --git a/drivers/Aqara/aqara-presence-sensor/src/discovery.lua b/drivers/Aqara/aqara-presence-sensor/src/discovery.lua index 88779fe6e5..fd68872679 100644 --- a/drivers/Aqara/aqara-presence-sensor/src/discovery.lua +++ b/drivers/Aqara/aqara-presence-sensor/src/discovery.lua @@ -11,9 +11,12 @@ function discovery.set_device_field(driver, device) -- persistent fields if device_cache_value ~= nil then + log.info_with({ hub_logs = true }, string.format("device found in cache. dni= %s", device.device_network_id)) device:set_field(fields.CREDENTIAL, device_cache_value.credential, { persist = true }) device:set_field(fields.DEVICE_IPV4, device_cache_value.ip, { persist = true }) device:set_field(fields.DEVICE_INFO, device_cache_value.device_info, { persist = true }) + else + log.error_with({ hub_logs = true }, string.format("device not found in cache. dni= %s", device.device_network_id)) end driver.datastore.discovery_cache[device.device_network_id] = nil @@ -40,7 +43,7 @@ local function try_add_device(driver, device_dni, device_ip) if driver.datastore.discovery_cache[device_dni] and driver.datastore.discovery_cache[device_dni].credential then log.info(string.format("use stored credential. This may have expired. dni= %s, ip= %s", device_dni, device_ip)) else - log.error(string.format("Failed to get credential. dni= %s, ip= %s", device_dni, device_ip)) + log.error_with({ hub_logs = true }, string.format("Failed to get credential. The device appears to have already generated a credential. In that case, a device reset is needed to generate a new credential. dni= %s, ip= %s", device_dni, device_ip)) return "credential not found" end else @@ -48,13 +51,14 @@ local function try_add_device(driver, device_dni, device_ip) driver.datastore.discovery_cache[device_dni].credential = credential end - log.info(string.format("try_create_device. dni= %s, ip= %s", device_dni, device_ip)) + log.info_with({ hub_logs = true }, string.format("try_create_device. dni= %s, ip= %s", device_dni, device_ip)) processing_devices[device_dni] = true driver:try_create_device(create_device_msg) return nil end function discovery.device_added(driver, device) + log.info_with({ hub_logs = true }, string.format("device_added. dni= %s", device.device_network_id)) discovery.set_device_field(driver, device) processing_devices[device.device_network_id] = nil driver.lifecycle_handlers.init(driver, device) @@ -96,6 +100,7 @@ local function discovery_device(driver) end function discovery.do_network_discovery(driver, _, should_continue) + log.info_with({ hub_logs = true }, string.format("discovery start for Aqara FP2")) while should_continue() do discovery_device(driver) socket.sleep(1) diff --git a/drivers/Aqara/aqara-presence-sensor/src/fp2/api.lua b/drivers/Aqara/aqara-presence-sensor/src/fp2/api.lua index 1c0a2ebb2b..4f27a277a3 100644 --- a/drivers/Aqara/aqara-presence-sensor/src/fp2/api.lua +++ b/drivers/Aqara/aqara-presence-sensor/src/fp2/api.lua @@ -39,16 +39,8 @@ local function process_rest_response(response, err, partial) end end -local function retry_fn(retry_attempts) - local count = 0 - return function() - count = count + 1 - return count < retry_attempts - end -end - local function do_get(api_instance, path) - return process_rest_response(api_instance.client:get(path, api_instance.headers, retry_fn(5))) + return process_rest_response(RestClient.one_shot_get(api_instance.base_url .. path, api_instance.headers, api_instance.socket_builder)) end function fp2_api.new_device_manager(device_ip, bridge_info, socket_builder) @@ -57,7 +49,7 @@ function fp2_api.new_device_manager(device_ip, bridge_info, socket_builder) return setmetatable( { headers = ADDITIONAL_HEADERS, - client = RestClient.new(base_url, socket_builder), + socket_builder = socket_builder, base_url = base_url, }, fp2_api ) diff --git a/drivers/Aqara/aqara-presence-sensor/src/fp2/device_manager.lua b/drivers/Aqara/aqara-presence-sensor/src/fp2/device_manager.lua index 1e678d80c9..66d4e8ac6c 100644 --- a/drivers/Aqara/aqara-presence-sensor/src/fp2/device_manager.lua +++ b/drivers/Aqara/aqara-presence-sensor/src/fp2/device_manager.lua @@ -256,6 +256,7 @@ function device_manager.is_valid_connection(driver, device, conn_info) device.device_network_id)) return false end + local _, err, status = conn_info:get_attr() if err or status ~= 200 then log.warn(string.format( diff --git a/drivers/Aqara/aqara-presence-sensor/src/fp2/discovery_helper.lua b/drivers/Aqara/aqara-presence-sensor/src/fp2/discovery_helper.lua index 7a0e28917a..dcc24b61dd 100644 --- a/drivers/Aqara/aqara-presence-sensor/src/fp2/discovery_helper.lua +++ b/drivers/Aqara/aqara-presence-sensor/src/fp2/discovery_helper.lua @@ -33,10 +33,17 @@ function discovery_helper.get_device_create_msg(driver, device_dni, device_ip) return nil end + local device_label = device_info.label or "Aqara-FP2" + if device_dni then + -- To make it easier to distinguish devices, add the last four letters of dni to the label + -- for example, if device_info.label is "Aqara-FP2" and device_dni is "00:11:22:33:44:55", then device_label will be "Aqara-FP2 (4455)" + device_label = string.format("%s (%s)", device_label, string.sub(string.gsub(tostring(device_dni), ":", ""), -4)) + end + local create_device_msg = { type = "LAN", device_network_id = device_dni, - label = device_info.label, + label = device_label, profile = "aqara-fp2-zoneDetection", manufacturer = device_info.manufacturerName, model = device_info.modelName, diff --git a/drivers/Aqara/aqara-presence-sensor/src/init.lua b/drivers/Aqara/aqara-presence-sensor/src/init.lua index 4080650618..c0d0e953b9 100644 --- a/drivers/Aqara/aqara-presence-sensor/src/init.lua +++ b/drivers/Aqara/aqara-presence-sensor/src/init.lua @@ -20,32 +20,27 @@ local function status_update(driver, device) local conn_info = device:get_field(fields.CONN_INFO) if not conn_info then log.warn(string.format("refresh : failed to find conn_info, dni = %s", device.device_network_id)) + return false, "failed to find conn_info" else local resp, err, status = conn_info:get_attr() if err or status ~= 200 then log.error(string.format("refresh : failed to get attr, dni= %s, err= %s, status= %s", device.device_network_id, err, status)) - if status == 404 then - device:offline() - end + return false, "failed to get attr" else driver.device_manager.handle_status(driver, device, resp) end end + return true end local function create_sse(driver, device, credential) local conn_info = device:get_field(fields.CONN_INFO) - if not driver.device_manager.is_valid_connection(driver, device, conn_info) then - log.warn("create_sse : invalid connection") - return - end - local sse_url = driver.device_manager.get_sse_url(driver, device, conn_info) if not sse_url then - log.error("failed to get sse_url") + log.error_with({ hub_logs = true }, "failed to get sse_url") else log.trace(string.format("Creating SSE EventSource for %s, sse_url= %s", device.device_network_id, sse_url)) local label = string.format("%s-SSE", device.device_network_id) @@ -64,7 +59,16 @@ local function create_sse(driver, device, credential) end eventsource.onopen = function() + log.info_with({ hub_logs = true }, string.format("Eventsource open: dni= %s", device.device_network_id)) device:online() + 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)) + success, err = status_update(driver, device) + if not success then + log.error_with({ hub_logs = true }, string.format("Failed to status_update during eventsource.onopen again, err = %s dni= %s", err, device.device_network_id)) + end + end end local old_eventsource = device:get_field(fields.EVENT_SOURCE) @@ -104,14 +108,11 @@ end local function check_and_update_connection(driver, device) local conn_info = device:get_field(fields.CONN_INFO) - if not driver.device_manager.is_valid_connection(driver, device, conn_info) then - device:offline() + local eventsource = device:get_field(fields.EVENT_SOURCE) + if eventsource and eventsource.ready_state == eventsource.ReadyStates.OPEN then + log.info(string.format("SSE connection is being maintained well, dni = %s", device.device_network_id)) + elseif not driver.device_manager.is_valid_connection(driver, device, conn_info) then find_new_connection(driver, device) - conn_info = device:get_field(fields.CONN_INFO) - end - - if driver.device_manager.is_valid_connection(driver, device, conn_info) then - device:online() end end @@ -132,8 +133,11 @@ end local function do_refresh(driver, device, cmd) - check_and_update_connection(driver, device) - status_update(driver, device) + local success, err = status_update(driver, device) + if not success then + log.info(string.format("Failed to status_update during do_refresh, err = %s dni= %s", err, device.device_network_id)) + check_and_update_connection(driver, device) + end driver.device_manager.init_presence(driver, device) driver.device_manager.init_movement(driver, device) driver.device_manager.init_activity(driver, device) @@ -163,6 +167,7 @@ local function device_init(driver, device) if device:get_field(fields._INIT) then return end + device:set_field(fields._INIT, true, { persist = false }) local device_dni = device.device_network_id driver.controlled_devices[device_dni] = device @@ -177,19 +182,19 @@ local function device_init(driver, device) local credential = device:get_field(fields.CREDENTIAL) if not credential then - log.error("failed to find credential.") + log.error_with({ hub_logs = true }, "failed to find credential.") device:offline() return end + driver.device_manager.set_zone_info_to_latest_state(driver, device) + log.trace(string.format("Creating device monitoring for %s", device.device_network_id)) create_monitoring_thread(driver, device, device_info) - update_connection(driver, device, device_ip, device_info) - driver.device_manager.set_zone_info_to_latest_state(driver, device) + update_connection(driver, device, device_ip, device_info) do_refresh(driver, device, nil) - device:set_field(fields._INIT, true, { persist = false }) end local function device_info_changed(driver, device, event, args) @@ -210,8 +215,6 @@ local lan_driver = Driver("aqara-fp2", [capabilities.refresh.commands.refresh.NAME] = do_refresh, }, [multipleZonePresence.id] = { - [multipleZonePresence.commands.createZone.name] = multipleZonePresence.commands.createZone.handler, - [multipleZonePresence.commands.deleteZone.name] = multipleZonePresence.commands.deleteZone.handler, [multipleZonePresence.commands.updateZoneName.name] = multipleZonePresence.commands.updateZoneName.handler, } }, diff --git a/drivers/Aqara/aqara-presence-sensor/src/lunchbox/rest.lua b/drivers/Aqara/aqara-presence-sensor/src/lunchbox/rest.lua index e79507ef73..dec3a28a37 100644 --- a/drivers/Aqara/aqara-presence-sensor/src/lunchbox/rest.lua +++ b/drivers/Aqara/aqara-presence-sensor/src/lunchbox/rest.lua @@ -182,6 +182,7 @@ local function handle_response(sock) if api_version >= 9 then local response, err = Response.tcp_source(sock) if err or (not response) then return response, (err or "unknown error") end + if response.status == 403 then return response, "403 Forbidden" end return response, response:fill_body() end -- called select right before passing in so we receive immediately diff --git a/drivers/Aqara/aqara-presence-sensor/src/lunchbox/sse/eventsource.lua b/drivers/Aqara/aqara-presence-sensor/src/lunchbox/sse/eventsource.lua index 0b5244bcd1..5afc79fc98 100644 --- a/drivers/Aqara/aqara-presence-sensor/src/lunchbox/sse/eventsource.lua +++ b/drivers/Aqara/aqara-presence-sensor/src/lunchbox/sse/eventsource.lua @@ -343,8 +343,10 @@ local function open_action(source) return else --- real error, close the connection. - source._sock:close() - source._sock = nil + if source._sock ~= nil then + source._sock:close() + source._sock = nil + end source.ready_state = EventSource.ReadyStates.CLOSED return nil, err, partial end @@ -360,8 +362,10 @@ local function open_action(source) return else --- real error, close the connection. - source._sock:close() - source._sock = nil + if source._sock ~= nil then + source._sock:close() + source._sock = nil + end source.ready_state = EventSource.ReadyStates.CLOSED return nil, err, partial end @@ -373,8 +377,10 @@ local function open_action(source) return else --- real error, close the connection. - source._sock:close() - source._sock = nil + if source._sock ~= nil then + source._sock:close() + source._sock = nil + end source.ready_state = EventSource.ReadyStates.CLOSED return nil, err, partial end