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

Rolling up beta to production #1123

Merged
merged 8 commits into from
Dec 19, 2023
44 changes: 44 additions & 0 deletions drivers/SmartThings/matter-button/profiles/6-button-battery.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: 6-button-battery
components:
- id: main
capabilities:
- id: button
version: 1
- id: battery
version: 1
- id: firmwareUpdate
version: 1
- id: refresh
version: 1
categories:
- name: RemoteController
- id: button2
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
- id: button3
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
- id: button4
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
- id: button5
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
- id: button6
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
42 changes: 42 additions & 0 deletions drivers/SmartThings/matter-button/profiles/6-button.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: 6-button
components:
- id: main
capabilities:
- id: button
version: 1
- id: firmwareUpdate
version: 1
- id: refresh
version: 1
categories:
- name: RemoteController
- id: button2
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
- id: button3
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
- id: button4
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
- id: button5
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
- id: button6
capabilities:
- id: button
version: 1
categories:
- name: RemoteController
2 changes: 1 addition & 1 deletion drivers/SmartThings/matter-button/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ local START_BUTTON_PRESS = "__start_button_press"
local TIMEOUT_THRESHOLD = 10 --arbitrary timeout
local HELD_THRESHOLD = 1
-- this is the number of buttons for which we have a static profile already made
local STATIC_PROFILE_SUPPORTED = {2, 4, 8}
local STATIC_PROFILE_SUPPORTED = {2, 4, 6, 8}

local COMPONENT_TO_ENDPOINT_MAP = "__component_to_endpoint_map"
local DEFERRED_CONFIGURE = "__DEFERRED_CONFIGURE"
Expand Down
60 changes: 51 additions & 9 deletions drivers/SmartThings/sonos/src/ssdp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,32 @@ SONOS_SSDP_SEARCH_TERM = "urn:smartspeaker-audio:service:SpeakerGroup:1"
local SSDP = {}

local function process_response(val)
local info = {}
-- check first line assuming it's the HTTP Status Line, which if not is invalid
local status_line = string.match(val, "([^\r\n]*)\r\n")
if not (status_line and string.match(status_line, "HTTP/1.1 200 OK")) then
return nil, string.format("SSDP Response HTTP Status Line missing or not '200 OK': %q", status_line)
end
-- strip status line from payload
val = string.gsub(val, "HTTP/1.1 200 OK\r\n", "", 1)
for k, v in string.gmatch(val, "([%g]+): ([%g ]*)\r\n") do

local info = {}
-- iterate line-by-line by splitting on `\r\n`
for l in string.gmatch(val, "([^\r\n]*)\r\n") do
if l == nil or l == "" then
break
end
-- SSDP Messages use the HTTP/1.1 Header Field rules described in RFC 2616, 4.2: https://datatracker.ietf.org/doc/html/rfc2616#section-4.2
-- This pattern extracts the Key/Value pairs in to a Lua table via the two capture groups.
-- The key capture group is composed entirely of a negating matcher to exclude illegal characters, ending at the `:`.
-- The RFC states that after the colon there may be any arbitrary amount of leading space between the colon
-- and the value, and that the value shouldn't have any trailing whitespace, so we exclude those as well.
-- The original Luncheon implementation of this Lua Pattern used iteration and detected the `;` separator
-- that indicates key/value parameters, however, we don't make that distinction here and instead leave parsing
-- values with parameters to the consumers of the output of this function.
local k, v = string.match(l, '([^%c()<>@,;:\\"/%[%]?={} \t]+):%s*(.-)%s*$')
if k == nil or k == "" then
return nil, string.format("Couldn't parse header/value pair for line %q", l)
end
info[string.lower(k)] = v
end
return info
Expand All @@ -21,7 +44,10 @@ function SSDP.check_headers_contain(response, ...)
local header_vals = table.pack(...)
for _, header in ipairs(header_vals) do
if header ~= nil then
if not response[header] then return false end
if not response[header] then
log.warn("No header available for key " .. st_utils.stringify_table(header))
return false
end
end
end
return true
Expand Down Expand Up @@ -74,12 +100,28 @@ function SSDP.search(search_term, callback)
local val, rip, _ = s:receivefrom()

if val then
local headers = process_response(val)
local headers, err = process_response(val)

if err ~= nil then
log.error(err or "Unknown error while parsing SSDP response headers")
goto continue
end

if headers == nil then
log.error("No headers found in SSDP response")
goto continue
end

if headers["st"] ~= search_term then
log.trace("Received SSDP response for different search term, skipping.")
goto continue
end

-- log all SSDP responses, even if they don't have proper headers
-- log all parseable SSDP responses for the search term,
-- even if they don't have proper headers.
log.debug_with({ hub_logs = true },
string.format("Received response for Sonos search with headers [%s], processing details",
st_utils.stringify_table(headers)))
string.format("Received response for Sonos search with headers [%s], processing details",
st_utils.stringify_table(headers)))
if
-- we don't explicitly check "st" because we don't index in to the contained
-- value so the equality check suffices as a nil check as well.
Expand All @@ -89,8 +131,7 @@ function SSDP.search(search_term, callback)
"location",
"groupinfo.smartspeaker.audio",
"websock.smartspeaker.audio",
"household.smartspeaker.audio") and
headers["st"] == search_term and headers["server"]:find("Sonos")
"household.smartspeaker.audio") and headers["server"]:find("Sonos")
then
local ip =
headers["location"]:match("http://([^,/]+):[^/]+/.+%.xml")
Expand Down Expand Up @@ -145,6 +186,7 @@ function SSDP.search(search_term, callback)
"error receiving discovery replies for search term: %s",
rip))
end
::continue::
end
s:close()
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ local t_utils = require "integration_test.utils"
local Battery = (require "st.zwave.CommandClass.Battery")({ version=1 })
local Configuration = (require "st.zwave.CommandClass.Configuration")({ version=1 })
local SensorMultilevel = (require "st.zwave.CommandClass.SensorMultilevel")({ version=5 })
local SensorBinary = (require "st.zwave.CommandClass.SensorBinary")({ version = 2 })
local WakeUp = (require "st.zwave.CommandClass.WakeUp")({ version=1 })
local Notification = (require "st.zwave.CommandClass.Notification")({ version=4 })

Expand Down Expand Up @@ -159,19 +158,6 @@ test.register_coroutine_test(
Configuration:Set({parameter_number=32, size=2, configuration_value=4320})
)
)
test.socket.zwave:__expect_send(
zw_test_utils.zwave_test_build_send_command(
mock_device,
SensorBinary:Get({sensor_type = SensorBinary.sensor_type.FREEZE})
)
)
test.socket.zwave:__expect_send(
zw_test_utils.zwave_test_build_send_command(
mock_device,
SensorBinary:Get({sensor_type = SensorBinary.sensor_type.SMOKE})
)
)

end
)

Expand Down
Loading