Skip to content

Commit 6f9bb96

Browse files
authored
Merge pull request #2107 from SmartThingsCommunity/main
Rolling up main to beta
2 parents db2c496 + d773c03 commit 6f9bb96

File tree

38 files changed

+1651
-39
lines changed

38 files changed

+1651
-39
lines changed

drivers/Aqara/aqara-presence-sensor/src/discovery.lua

+12-5
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ function discovery.set_device_field(driver, device)
2222
driver.datastore.discovery_cache[device.device_network_id] = nil
2323
end
2424

25-
local function update_device_discovery_cache(driver, dni, ip)
26-
local device_info = driver.discovery_helper.get_device_info(driver, dni, ip)
25+
local function update_device_discovery_cache(driver, dni, ip, device_info)
2726
if driver.datastore.discovery_cache[dni] == nil then
2827
driver.datastore.discovery_cache[dni] = {}
2928
end
@@ -33,9 +32,10 @@ end
3332

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

37-
update_device_discovery_cache(driver, device_dni, device_ip)
38-
local create_device_msg = driver.discovery_helper.get_device_create_msg(driver, device_dni, device_ip)
37+
update_device_discovery_cache(driver, device_dni, device_ip, device_info)
38+
local create_device_msg = driver.discovery_helper.get_device_create_msg(driver, device_dni, device_ip, device_info)
3939

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

@@ -93,7 +93,14 @@ local function discovery_device(driver)
9393

9494
for dni, ip in pairs(unknown_discovered_devices) do
9595
log.trace(string.format("unknown dni= %s, ip= %s", dni, ip))
96-
if not processing_devices[dni] then
96+
local is_already_added = false
97+
for _, device in pairs(driver:get_devices()) do
98+
if device.device_network_id == dni then
99+
is_already_added = true
100+
break
101+
end
102+
end
103+
if (not processing_devices[dni]) and (not is_already_added) then
97104
try_add_device(driver, dni, ip)
98105
end
99106
end

drivers/Aqara/aqara-presence-sensor/src/fields.lua

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ local fields = {
1010
EVENT_SOURCE = "eventsource",
1111
MONITORING_TIMER = "monitoring_timer",
1212
CREDENTIAL = "credential",
13-
_INIT = "init"
13+
_INIT = "init",
14+
CONNECTION_STATUS = "connection_status"
1415
}
1516

1617
return fields

drivers/Aqara/aqara-presence-sensor/src/fp2/discovery_helper.lua

+7-5
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ function discovery_helper.get_service_type_and_domain()
2525
return SERVICE_TYPE, DOMAIN
2626
end
2727

28-
function discovery_helper.get_device_create_msg(driver, device_dni, device_ip)
29-
local device_info = fp2_api.get_info(device_ip, fp2_api.labeled_socket_builder(device_dni))
30-
28+
function discovery_helper.get_device_create_msg(driver, device_dni, device_ip, device_info)
3129
if not device_info then
32-
log.warn("failed to create device create msg. device_info is nil.")
33-
return nil
30+
device_info = fp2_api.get_info(device_ip, fp2_api.labeled_socket_builder(device_dni))
31+
32+
if not device_info then
33+
log.warn("failed to create device create msg. device_info is nil.")
34+
return nil
35+
end
3436
end
3537

3638
local device_label = device_info.label or "Aqara-FP2"

drivers/Aqara/aqara-presence-sensor/src/init.lua

+48-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
local log = require "log"
2+
local socket = require "cosock.socket"
23
local capabilities = require "st.capabilities"
34
local Driver = require "st.driver"
45
local discovery = require "discovery"
@@ -54,13 +55,22 @@ local function create_sse(driver, device, credential)
5455
end
5556

5657
eventsource.onerror = function()
57-
log.error(string.format("Eventsource error: dni= %s", device.device_network_id))
58+
local DISCONNECTED_STATUS = "disconnected"
59+
local connection_status = device:get_field(fields.CONNECTION_STATUS)
60+
if connection_status and connection_status == DISCONNECTED_STATUS then
61+
log.error(string.format("Eventsource error: dni= %s", device.device_network_id))
62+
else
63+
log.error_with({ hub_logs = true }, string.format("Eventsource error: disconnected, dni= %s", device.device_network_id))
64+
device:set_field(fields.CONNECTION_STATUS, DISCONNECTED_STATUS)
65+
end
5866
device:offline()
67+
5968
end
6069

6170
eventsource.onopen = function()
6271
log.info_with({ hub_logs = true }, string.format("Eventsource open: dni= %s", device.device_network_id))
6372
device:online()
73+
device:set_field(fields.CONNECTION_STATUS, "connected")
6474
local success, err = status_update(driver, device)
6575
if not success then
6676
log.warn(string.format("Failed to status_update during eventsource.onopen, err = %s dni= %s", err, device.device_network_id))
@@ -125,7 +135,6 @@ local function create_monitoring_thread(driver, device, device_info)
125135
local monitoring_interval = DEFAULT_MONITORING_INTERVAL
126136
local new_timer = device.thread:call_on_schedule(monitoring_interval, function()
127137
check_and_update_connection(driver, device)
128-
driver.device_manager.device_monitor(driver, device, device_info)
129138
end, "monitor_timer")
130139
device:set_field(fields.MONITORING_TIMER, new_timer)
131140
end
@@ -145,22 +154,27 @@ end
145154

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

153164
if err or status ~= 200 then
154-
log.error(string.format("remove : failed to get remove, dni= %s, err= %s, status= %s", device.device_network_id,
165+
log.error_with({ hub_logs = true }, string.format("remove : failed to get remove, dni= %s, err= %s, status= %s", device.device_network_id,
155166
err,
156167
status))
168+
else
169+
log.info_with({ hub_logs = true }, string.format("Device removed: token reset success. dni= %s", device.device_network_id))
157170
end
158171
end
159172

160173
local eventsource = device:get_field(fields.EVENT_SOURCE)
161174
if eventsource then
162175
eventsource:close()
163176
end
177+
driver.removing_devices = driver.removing_devices - 1
164178
end
165179

166180
local function device_init(driver, device)
@@ -194,13 +208,41 @@ local function device_init(driver, device)
194208

195209
update_connection(driver, device, device_ip, device_info)
196210

211+
local eventsource = device:get_field(fields.EVENT_SOURCE)
212+
if not eventsource then
213+
log.error_with({ hub_logs = true }, "failed to create EVENT_SOURCE.")
214+
device:offline()
215+
return
216+
end
217+
197218
do_refresh(driver, device, nil)
198219
end
199220

200221
local function device_info_changed(driver, device, event, args)
201222
do_refresh(driver, device, nil)
202223
end
203224

225+
local function driver_lifecycle_handler(driver, event_name)
226+
log.info(string.format("driver lifecycle event :'%s'", event_name))
227+
if event_name == "shutdown" then
228+
local MAXIMUM_WAITING_TIME = 30
229+
local WAITING_TIME = 1
230+
local total_waiting_time = 0
231+
232+
while (driver.removing_devices > 0) do
233+
log.info("waiting for all devices to be removed")
234+
total_waiting_time = total_waiting_time + WAITING_TIME
235+
socket.sleep(WAITING_TIME) -- wait for 1 seconds
236+
237+
if total_waiting_time > MAXIMUM_WAITING_TIME then
238+
log.error_with({ hub_logs = true }, "maximum waiting time exceeded")
239+
end
240+
end
241+
log.info(string.format("forced exit"))
242+
os.exit(0)
243+
end
244+
end
245+
204246
local lan_driver = Driver("aqara-fp2",
205247
{
206248
discovery = discovery.do_network_discovery,
@@ -210,6 +252,7 @@ local lan_driver = Driver("aqara-fp2",
210252
infoChanged = device_info_changed,
211253
removed = device_removed
212254
},
255+
driver_lifecycle = driver_lifecycle_handler,
213256
capability_handlers = {
214257
[capabilities.refresh.ID] = {
215258
[capabilities.refresh.commands.refresh.NAME] = do_refresh,
@@ -221,6 +264,7 @@ local lan_driver = Driver("aqara-fp2",
221264
discovery_helper = fp2_discovery_helper,
222265
device_manager = fp2_device_manager,
223266
controlled_devices = {},
267+
removing_devices = 0
224268
}
225269
)
226270

drivers/Aqara/aqara-presence-sensor/src/lunchbox/sse/eventsource.lua

+12-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ local util = require "lunchbox.util"
77
local Request = require "luncheon.request"
88
local Response = require "luncheon.response"
99

10+
local MAX_RECONNECT_TIME_SEC = 60
11+
1012
--- A pure Lua implementation of the EventSource interface.
1113
--- The EventSource interface represents the client end of an HTTP(S)
1214
--- connection that receives an event stream following the Server-Sent events
@@ -302,6 +304,11 @@ local function connecting_action(source)
302304
return nil, err or "nil response from Response.tcp_source"
303305
end
304306

307+
if response.status == 401 then
308+
source._reconnect = false
309+
return nil, "Server response is 401 Unauthorized, stop reconnect", { response.status, response.status_msg }
310+
end
311+
305312
if response.status ~= 200 then
306313
return nil, "Server responded with status other than 200 OK", { response.status, response.status_msg }
307314
end
@@ -317,6 +324,8 @@ local function connecting_action(source)
317324
end
318325

319326
source.ready_state = EventSource.ReadyStates.OPEN
327+
source._reconnect = true
328+
source._reconnect_time_millis = 1000
320329

321330
if type(source.onopen) == "function" then
322331
source.onopen()
@@ -418,7 +427,9 @@ local function closed_action(source)
418427

419428
local sleep_time_secs = source._reconnect_time_millis / 1000.0
420429
socket.sleep(sleep_time_secs)
421-
430+
if source._reconnect_time_millis <= MAX_RECONNECT_TIME_SEC * 1000 then
431+
source._reconnect_time_millis = source._reconnect_time_millis + 1000.0
432+
end
422433
source.ready_state = EventSource.ReadyStates.CONNECTING
423434
end
424435
end

drivers/SmartThings/matter-switch/profiles/light-color-level-fan.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ components:
1515
config:
1616
values:
1717
- key: "colorTemperature.value"
18-
range: [ 2200, 6500 ]
18+
range: [ 2700, 6500 ]
1919
- id: colorControl
2020
version: 1
2121
- id: fanMode

drivers/SmartThings/matter-switch/src/init.lua

+6
Original file line numberDiff line numberDiff line change
@@ -919,12 +919,18 @@ local function on_off_attr_handler(driver, device, ib, response)
919919
else
920920
device:emit_event_for_endpoint(ib.endpoint_id, capabilities.switch.switch.off())
921921
end
922+
if type(device.register_native_capability_attr_handler) == "function" then
923+
device:register_native_capability_attr_handler("switch", "switch")
924+
end
922925
end
923926

924927
local function level_attr_handler(driver, device, ib, response)
925928
if ib.data.value ~= nil then
926929
local level = math.floor((ib.data.value / 254.0 * 100) + 0.5)
927930
device:emit_event_for_endpoint(ib.endpoint_id, capabilities.switchLevel.level(level))
931+
if type(device.register_native_capability_attr_handler) == "function" then
932+
device:register_native_capability_attr_handler("switchLevel", "level")
933+
end
928934
end
929935
end
930936

drivers/SmartThings/philips-hue/src/fields.lua

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ local Fields = {
1919
DEVICE_TYPE = "devicetype",
2020
EVENT_SOURCE = "eventsource",
2121
GAMUT = "gamut",
22+
GROUPS = "groups",
23+
GROUPS_SCAN_QUEUE = "groups_scan_queue",
2224
HUE_DEVICE_ID = "hue_device_id",
2325
IPV4 = "ipv4",
2426
IS_ONLINE = "is_online",

0 commit comments

Comments
 (0)