Skip to content
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

[Aqara] Presence Sensor FP2 #1546

Merged
merged 10 commits into from
Sep 13, 2024
Merged

Conversation

seojune79
Copy link
Contributor

Check all that apply

Type of Change

  • [O] WWST Certification Request
    • If this is your first time contributing code:
      • I have reviewed the README.md file
      • I have reviewed the CODE_OF_CONDUCT.md file
      • I have signed the CLA
    • [O] I plan on entering a WWST Certification Request or have entered a request through the WWST Certification console at developer.smartthings.com
  • Bug fix
  • [O] New feature
  • Refactor

Checklist

  • [O] I have performed a self-review of my code
  • [O] I have commented my code in hard-to-understand areas
  • [O] I have verified my changes by testing with a device or have communicated a plan for testing
  • [O] I am adding new behavior, such as adding a sub-driver, and have added and run new unit tests to cover the new behavior

Description of Change

Summary of Completed Tests

Copy link

Duplicate profile check: Passed - no duplicate profiles detected.

Copy link

Copy link

github-actions bot commented Jul 26, 2024

Test Results

   62 files    375 suites   0s ⏱️
1 822 tests 1 822 ✅ 0 💤 0 ❌
3 146 runs  3 146 ✅ 0 💤 0 ❌

Results for commit 640f066.

♻️ This comment has been updated with latest results.

Copy link

github-actions bot commented Jul 26, 2024

Minimum allowed coverage is 90%

Generated by 🐒 cobertura-action against 640f066

@varzac
Copy link
Contributor

varzac commented Jul 29, 2024

For LAN devices we need to include a search-parameters.yml to allow the hub to only start the driver if there is a matching device on the network.

@varzac
Copy link
Contributor

varzac commented Jul 29, 2024

I have an FP2 so I decided to try to discover it. Currently I am just getting:

2024-07-29T16:17:20.207227119Z TRACE aqara-presence-sensor  try_add_device : dni= ***, ip= 192.168.1.146
2024-07-29T16:17:24.910038642Z ERROR aqara-presence-sensor  get_credential : ip = 192.168.1.146, failed to get token, error = closed
2024-07-29T16:17:24.915560443Z ERROR aqara-presence-sensor  credential is nil
2024-07-29T16:17:24.927665159Z ERROR aqara-presence-sensor  failed to get credential. dni= ***, ip= 192.168.1.146

I made sure to update the FP2 to the latest firmware, but if there is anything else needed to test let me know.

@seojune79
Copy link
Contributor Author

For LAN devices we need to include a search-parameters.yml to allow the hub to only start the driver if there is a matching device on the network.

I added it.

@seojune79
Copy link
Contributor Author

I have an FP2 so I decided to try to discover it. Currently I am just getting:

2024-07-29T16:17:20.207227119Z TRACE aqara-presence-sensor  try_add_device : dni= ***, ip= 192.168.1.146
2024-07-29T16:17:24.910038642Z ERROR aqara-presence-sensor  get_credential : ip = 192.168.1.146, failed to get token, error = closed
2024-07-29T16:17:24.915560443Z ERROR aqara-presence-sensor  credential is nil
2024-07-29T16:17:24.927665159Z ERROR aqara-presence-sensor  failed to get credential. dni= ***, ip= 192.168.1.146

I made sure to update the FP2 to the latest firmware, but if there is anything else needed to test let me know.

You'll need to use the firmware that will be released in August to enroll in the SmartThings Hub. If you need that firmware, please let me know the information below in the Aqara Home app.

  • Region
  • Account
  • FP2's Accessory ID

You give me the information and our developers will request Equipment diagnosis permission application authorization. You'll have to approve it. After that, our developers will update your FP2 to that firmware.(FP2 must be online to be updated.)

How to connect to your SmartThings hub after the FP2 firmware update.

  1. The FP2 must be enrolled in the Aqara Home app.
  2. The SmartThings hub and FP2 must be connected to the same network.
  3. Your SmartThings hub must have the current driver installed.
  4. "Scan nearby" in the SmartThings app and the FP2 will register with the SmartThings hub.

@lelandblue
Copy link
Contributor

@seojune79 Can you please clarify, what testing have you completed to date? I noticed this was missing from the original message in this PR, can you please add or share more details?

@seojune79
Copy link
Contributor Author

@seojune79 Can you please clarify, what testing have you completed to date? I noticed this was missing from the original message in this PR, can you please add or share more details?

We tested with Samsung to ensure that the following events are handled the same as in the Aqara Home app.
(Settings can only be made in the Aqara Home app, and depending on the setting, the same event will occur in both the Aqara Home app and the SmartThings app.)

  • Mode change: stse.deviceMode
  • Zone detection: presenceSensor, movementSensor, multipleZonePresence, illuminanceMeasurement
  • Fall detection: activitySensor, presenceSensor, illuminanceMeasurement
  • Sleep monitoring: illuminanceMeasurement

end

function device_manager.movement_handler(driver, device, zone, evt_value)
if not device:supports_capability(PresenceSensor) then return end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is probably a copy-paste issue and should be checking for MovementSensor instead of PresenceSensor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix it.

@lelandblue
Copy link
Contributor

@tpmanley or @varzac Could you review the latest commit when you get a chance and let me know if this review is good to proceed? Thank you.

tpmanley
tpmanley previously approved these changes Aug 9, 2024
Copy link
Contributor

@tpmanley tpmanley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of minor issues I suggest addressing before merging

drivers/Aqara/aqara-presence-sensor/config.yml Outdated Show resolved Hide resolved
local device_info = fp2_api.get_info(device_ip, fp2_api.labeled_socket_builder(device_dni))

if not device_info then
log.error(string.format("failed to create device create msg. device_info is nil. dni = %s"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is attempting to format a string with an argument but the argument isn't provided

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed the argument because it is nil

table.remove(mzp.zoneInfoTable, index)
deletedId = id
else
err = string.format("id %s doesn't exists", id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
err = string.format("id %s doesn't exists", id)
err = string.format("id %s doesn't exist", id)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix it.

zoneInfo.name = name
changedId = id
else
err = string.format("id %s doesn't exists", id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

Suggested change
err = string.format("id %s doesn't exists", id)
err = string.format("id %s doesn't exist", id)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see.

zoneInfo.state = state
changedId = id
else
err = string.format("id %s doesn't exists", id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
err = string.format("id %s doesn't exists", id)
err = string.format("id %s doesn't exist", id)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll fix it.

@varzac
Copy link
Contributor

varzac commented Aug 12, 2024

One issue I ran into was I edited the names of my Zones last week, however when looking today I see that the names have reverted to Zone 1, Zone 2, Zone 3. I don't know if that is due to ongoing development or something else.

Copy link
Contributor

@FreeMasen FreeMasen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Please add type hints/doc comments using the ldoc format
  2. All functions that may fail should return nil, "<error message>" to aid in debugging
  3. Error logs are reserved for fatal conditions, please use warn for know points of failure
  4. Consider using %q when using string.format with non-table/userdata values to get better formatting

local device_discovery_cache = {}

local function set_device_field(driver, device)
local device_cache_value = device_discovery_cache[device.device_network_id]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should check for nil here

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 credential = driver.discovery_helper.get_credential(driver, device_dni, device_ip)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: error messages are typically included after the value, this will make line 34 more helpful

function discovery.device_added(driver, device)
set_device_field(driver, device)
device_discovery_cache[device.device_network_id] = nil
driver.lifecycle_handlers.init(driver, device)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe you should be calling lifecycle handlers directly, this will be called by the framework

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this is needed in order to make sure init is called after added. Init requires the device fields to have been populated.

Comment on lines 50 to 51
local ip_table = discovery_mdns.find_ip_table_by_mdns(driver)
return ip_table
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needless assignment

Suggested change
local ip_table = discovery_mdns.find_ip_table_by_mdns(driver)
return ip_table
return discovery_mdns.find_ip_table_by_mdns(driver)

local ip_table = discovery.find_ip_table(driver)

for dni, ip in pairs(ip_table) do
if not known_devices or not known_devices[dni] then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why wold known_devices be nil here?


if not driver.device_manager.is_valid_connection(driver, device, conn_info) then
log.error("create_sse : invalid connection")
return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nil return w/o error in 2nd position

Comment on lines 54 to 56
-- sync
-- status_update(driver, device) -- for test
-- end of sync
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stale comments, please remove

local function find_new_connetion(driver, device)
local ip_table = discovery.find_ip_table(driver)
local ip = ip_table[device.device_network_id]
if ip then
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warn if nil?

end

local function configure_handler(driver, device, event, args)
-- no action
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for this function to be defined

)

lan_driver:run()
log.warn("lan driver exiting")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will never execute, please remove

@tpmanley tpmanley dismissed their stale review August 12, 2024 19:45

I'm seeing an issue with zone names reverting

@tpmanley
Copy link
Contributor

One issue I ran into was I edited the names of my Zones last week, however when looking today I see that the names have reverted to Zone 1, Zone 2, Zone 3. I don't know if that is due to ongoing development or something else.

I saw this too and reproduced it by rebooting my hub. The first multipleZonePresence.zoneState event generated after the reboot had the default "zone1" name again.

@seojune79
Copy link
Contributor Author

One issue I ran into was I edited the names of my Zones last week, however when looking today I see that the names have reverted to Zone 1, Zone 2, Zone 3. I don't know if that is due to ongoing development or something else.

Did it happen even though you didn't change the zone? If you experience that issue again, please share how to reproduce it.

@seojune79
Copy link
Contributor Author

One issue I ran into was I edited the names of my Zones last week, however when looking today I see that the names have reverted to Zone 1, Zone 2, Zone 3. I don't know if that is due to ongoing development or something else.

I saw this too and reproduced it by rebooting my hub. The first multipleZonePresence.zoneState event generated after the reboot had the default "zone1" name again.

Thanks. I've reproduced the issue on my FP2, I'll check it out.

@seojune79
Copy link
Contributor Author

One issue I ran into was I edited the names of my Zones last week, however when looking today I see that the names have reverted to Zone 1, Zone 2, Zone 3. I don't know if that is due to ongoing development or something else.

I saw this too and reproduced it by rebooting my hub. The first multipleZonePresence.zoneState event generated after the reboot had the default "zone1" name again.

I fixed it.

local conn_info = device:get_field(fields.CONN_INFO)
if not driver.device_manager.is_valid_connection(driver, device, conn_info) then
device:offline()
find_new_connetion(driver, device)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

find_new_connection

end


local function find_new_connetion(driver, device)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

find_new_connection

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you tell me more on this?

Copy link

@ldeora ldeora Aug 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a minor spelling mistake. Just wanted to make sure the function name matches.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. I fixed it.

@varzac
Copy link
Contributor

varzac commented Aug 20, 2024

I did have my Zone names disappear again. Otherwise the device has been working great for me. I don't know how the zone names were lost I just opened up the app and they were gone. There was a hub firmware update so there was a hub reboot. But I did re-name them and manually reboot the hub and the name persisted. Was the fix you added something that would only take affect the next time I named them?

@seojune79
Copy link
Contributor Author

Can someone let me know how this PR is going?

Copy link
Contributor

@cjswedes cjswedes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a few small things that aren't critical. Ill defer merging to @varzac and @tpmanley who have been testing with the device.

This is one of the best lan drivers I have reviewed, thank you!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please pull in the latest lunchbox version that exists in the philips hue driver. This will help with maintenance in the future when we add the library to the lua libs and no longer need to put it in these lan drivers.

Copy link

@ldeora ldeora Sep 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that broke the REST communication - at least in my case.

The very first GET for /authcode fails with error wantread now.

2024-09-27T22:46:41.855930580Z INFO Aqara Presence Sensor  54:EF:44:5C:4C:98 Performing SSL handshake for for REST Connection
2024-09-27T22:46:45.358401372Z INFO Aqara Presence Sensor  54:EF:44:5C:4C:98 Successfully created TCP connection
2024-09-27T22:47:45.440063966Z ERROR Aqara Presence Sensor  get_credential : ip = 192.168.1.121, failed to get token, error = wantread
2024-09-27T22:47:45.445295882Z WARN Aqara Presence Sensor  credential is nil
2024-09-27T22:47:45.450356841Z ERROR Aqara Presence Sensor  failed to get credential. dni= 54:EF:44:5C:4C:98, ip= 192.168.1.121

From the luasec documentation:

"wantread" and "wantwrite" indicates that a timeout occurred during the operation. Also, after the error message, the function returns the partial result of the transmission.

In the case of "wantread" or "wantwrite" errors, you should wait the connection to be ready for reading or writing, respectively, and call conn:receive again.

So the whole partial result handling wasn't that useless...

Also:

wantread" indicates that the operation was not finished because a timeout in the underline TCP connection prevents it of sending data.

This is rather cryptic, but it says that "I'm sending data, and I want my counterpart to READ; wantread"

lunarmodules/luasec#40

Comment on lines +247 to +250
else
log.error(string.format("handle_sse_event : unknown event type. dni = %s, event_type = '%s'",
device.device_network_id, event_type))
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

function discovery.device_added(driver, device)
set_device_field(driver, device)
device_discovery_cache[device.device_network_id] = nil
driver.lifecycle_handlers.init(driver, device)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this is needed in order to make sure init is called after added. Init requires the device fields to have been populated.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice discovery module. Very easy to review and understand what is happening.

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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this something that should be included in do_refresh it seems like it has a similar purpose to the init_presence, init_movement, and init_activity functions that are called there. Its not clear why zones aren't refreshed, and this is done via init.

drivers/Aqara/aqara-presence-sensor/src/init.lua Outdated Show resolved Hide resolved
@lelandblue
Copy link
Contributor

Can someone let me know how this PR is going?

Hey @seojune79 - @cjswedes just did a review of the new commit. Please feel welcome to review. As a result - This device will proceed through the WWST Certification process. I hope I have answered your question.

@seojune79
Copy link
Contributor Author

We made some code changes based on his comments.

@lelandblue lelandblue merged commit d2f9765 into SmartThingsCommunity:main Sep 13, 2024
15 checks passed
@ldeora
Copy link

ldeora commented Sep 25, 2024

Edit: latest commit (mainly rest.lua) broke it.

2024-09-27T22:47:45.440063966Z ERROR Aqara Presence Sensor  get_credential : ip = 192.168.1.121, failed to get token, error = wantread
2024-09-27T22:47:45.445295882Z WARN Aqara Presence Sensor  credential is nil
2024-09-27T22:47:45.450356841Z ERROR Aqara Presence Sensor  failed to get credential. dni= 54:EF:44:5C:4C:98, ip= 192.168.1.121

Can't add the device anymore! Removed the device, deleted the driver, added driver, tried to add the device. Tried it with main, beta, and this channel to make sure.

It worked about a month ago. Since then, changes were made to discovery.lua, init.lua, device_manager.lua...

Can someone please check if adding the device still works?

Device firmware: 1.2.7_0011.0080
Hub firmware: 000.053.00019
ST app (Android): 1.8.18.21

Device works with the Aqara Home app.

2024-09-25T10:34:03.597153457Z TRACE Aqara Presence Sensor  Setup driver aqara-fp2 with lifecycle handlers:
DeviceLifecycleDispatcher: aqara-fp2
  default_handlers:
    infoChanged:
    added:
    init:
    removed:
    driverSwitched:
  child_dispatchers:

2024-09-25T10:34:03.609944082Z TRACE Aqara Presence Sensor  Setup driver aqara-fp2 with Capability handlers:
CapabilityCommandDispatcher: aqara-fp2
  default_handlers:
    refresh:
      refresh
    multipleZonePresence:
      createZone
      deleteZone
      updateZoneName
  child_dispatchers:

2024-09-25T10:34:03.616156957Z INFO Aqara Presence Sensor  Created dispatcher [SecretDataDispatcher]aqara-fp2 that had no handlers
2024-09-25T10:34:03.628525582Z TRACE Aqara Presence Sensor  Setup driver aqara-fp2 with Secret Data handlers:
SecretDataDispatcher: aqara-fp2
  default_handlers:
  child_dispatchers:

2024-09-25T10:34:03.686260707Z TRACE Aqara Presence Sensor  Received event with handler driver_lifecycle
2024-09-25T10:34:03.707111916Z INFO Aqara Presence Sensor  received driver startupState: {"hub_zigbee_id":"KG2XAAILh00=","hub_node_id":1,"hub_ipv4":"192.168.1.116"}
2024-09-25T10:34:03.712373791Z TRACE Aqara Presence Sensor  Received event with handler discovery
2024-09-25T10:34:03.718594541Z INFO Aqara Presence Sensor  discovery_mdns.find_device_ips
2024-09-25T10:34:04.889382333Z INFO Aqara Presence Sensor  found_name = _Aqara-FP2._tcp
2024-09-25T10:34:04.941494333Z INFO Aqara Presence Sensor  ip = 192.168.1.109
2024-09-25T10:34:04.959243583Z INFO Aqara Presence Sensor  found_name = _Aqara-FP2._tcp
2024-09-25T10:34:04.972437916Z INFO Aqara Presence Sensor  ip = 192.168.1.109
2024-09-25T10:34:05.017133958Z TRACE Aqara Presence Sensor  unknown dni= 54:EF:44:5C:4C:98, ip= 192.168.1.109
2024-09-25T10:34:05.041282958Z TRACE Aqara Presence Sensor  try_add_device : dni= 54:EF:44:5C:4C:98, ip= 192.168.1.109
2024-09-25T10:34:05.075223208Z INFO Aqara Presence Sensor  54:EF:44:5C:4C:98 Creating TCP socket for REST Connection
2024-09-25T10:34:05.097121666Z INFO Aqara Presence Sensor  54:EF:44:5C:4C:98 Setting TCP socket timeout for REST Connection
2024-09-25T10:34:05.118858583Z INFO Aqara Presence Sensor  54:EF:44:5C:4C:98 Connecting TCP socket for REST Connection
2024-09-25T10:34:05.394824874Z INFO Aqara Presence Sensor  54:EF:44:5C:4C:98 Set Keepalive for TCP socket for REST Connection
2024-09-25T10:34:05.408426249Z INFO Aqara Presence Sensor  54:EF:44:5C:4C:98 Creating SSL wrapper for for REST Connection
2024-09-25T10:34:05.423615083Z INFO Aqara Presence Sensor  54:EF:44:5C:4C:98 Performing SSL handshake for for REST Connection
2024-09-25T10:34:07.962791666Z INFO Aqara Presence Sensor  54:EF:44:5C:4C:98 Successfully created TCP connection
2024-09-25T10:35:02.506882839Z TRACE Aqara Presence Sensor  Received event with handler discovery
2024-09-25T10:35:02.574833131Z TRACE Aqara Presence Sensor  Received event with handler driver_lifecycle

This is the complete log and it looks like the driver lifecycle ends?

@ldeora
Copy link

ldeora commented Sep 30, 2024

Proposal for a fix for the wantread, socket not ready issue:

#1654

@ldeora ldeora mentioned this pull request Sep 30, 2024
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants