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 main to beta #1644

Merged
merged 11 commits into from
Sep 23, 2024
56 changes: 44 additions & 12 deletions drivers/Aqara/aqara-lock/src/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ local seq_num = 0

local SHARED_KEY = "__shared_key"
local CLOUD_PUBLIC_KEY = "__cloud_public_key"
local SUPPORTED_ALARM_VALUES = { "damaged", "forcedOpeningAttempt", "unableToLockTheDoor", "notClosedForALongTime", "highTemperature", "attemptsExceeded" }

local function my_secret_data_handler(driver, device, secret_info)
if secret_info.secret_kind ~= "aqara" then return end
Expand Down Expand Up @@ -51,6 +52,24 @@ local function remoteControlShow(device)
end
end

local function comp_supported_alarm_values(last_alarm_values)
if not last_alarm_values then return false end
if #last_alarm_values~=#SUPPORTED_ALARM_VALUES then return false end
for k, v in pairs(last_alarm_values) do
if SUPPORTED_ALARM_VALUES[k]~=v then return false end
end
return true
end

local function device_init(self, device)
local last_alarm_values = device:get_latest_state("main", LockAlarm.ID, LockAlarm.supportedAlarmValues.NAME) or {}
if not comp_supported_alarm_values(last_alarm_values) then
device:emit_event(
LockAlarm.supportedAlarmValues(SUPPORTED_ALARM_VALUES, { visibility = { displayed = false } })
)
end
end

local function device_added(self, device)
remoteControlShow(device)
device:emit_event(Battery.battery(100))
Expand All @@ -68,6 +87,18 @@ local function toHex(value, length)
return utils.serialize_int(value, length, false, false)
end

local METHOD = {
LOCKED = "locked",
MANUAL = "manual",
FINGERPRINT = "fingerprint",
KEYPAD = "keypad",
RFID = "rfid",
RF447 = "rf447",
BLUETOOTH = "bluetooth",
COMMAND = "command",
NO_USE = ""
}

local function event_lock_handler(driver, device, evt_name, evt_value)
if evt_value == 0x1 then
device:emit_event(Lock.lock(evt_name))
Expand All @@ -78,11 +109,19 @@ end

local function event_unlock_handler(driver, device, evt_name, evt_value)
local id, label
if evt_value == 0x80020000 then -- one-time password
if evt_name == METHOD.RF447 then
evt_name = nil
id = nil
label = nil
elseif evt_name == METHOD.BLUETOOTH and evt_value == 2 then
evt_name = nil
id = nil
label = nil
elseif evt_value == 0x80020000 then -- one-time password
id = "OTP_STANDALONE"
label = nil
else
id, label = credential_utils.find_userLabel(driver, device, evt_value)
id, label = credential_utils.find_userLabel(driver, device, evt_value)
end
device:emit_event(Lock.lock.unlocked({ data = { method = evt_name, codeId = id, codeName = label } }))
device:emit_event(remoteControlStatus.remoteControlEnabled('false', { visibility = { displayed = false } }))
Expand Down Expand Up @@ -121,16 +160,6 @@ local function event_lock_status_handler(driver, device, evt_name, evt_value)
device:emit_event(LockAlarm.alarm.damaged())
end
end
local METHOD = {
LOCKED = "locked",
MANUAL = "manual",
FINGERPRINT = "fingerprint",
KEYPAD = "keypad",
RFID = "rfid",
BLUETOOTH = "bluetooth",
COMMAND = "command",
NO_USE = ""
}

local resource_id = {
["13.31.85"] = { event_name = METHOD.LOCKED, event_handler = event_lock_handler },
Expand All @@ -140,6 +169,7 @@ local resource_id = {
["13.42.85"] = { event_name = METHOD.FINGERPRINT, event_handler = event_unlock_handler },
["13.43.85"] = { event_name = METHOD.KEYPAD, event_handler = event_unlock_handler },
["13.44.85"] = { event_name = METHOD.RFID, event_handler = event_unlock_handler },
["13.151.85"] = { event_name = METHOD.RF447, event_handler = event_unlock_handler },
["13.45.85"] = { event_name = METHOD.BLUETOOTH, event_handler = event_unlock_handler },
["13.90.85"] = { event_name = METHOD.COMMAND, event_handler = event_unlock_handler },
["13.46.85"] = { event_name = METHOD.KEYPAD, event_handler = event_unlock_handler },
Expand Down Expand Up @@ -230,6 +260,7 @@ local aqara_locks_handler = {
NAME = "Aqara Doorlock K100",
supported_capabilities = {
Lock,
LockAlarm,
Battery,
lockCredentialInfo,
capabilities.refresh,
Expand All @@ -253,6 +284,7 @@ local aqara_locks_handler = {
}
},
lifecycle_handlers = {
init = device_init,
added = device_added
},
secret_data_handlers = {
Expand Down
4 changes: 4 additions & 0 deletions drivers/Aqara/aqara-lock/src/test/test_aqara_lock.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ local mock_device = test.mock_device.build_test_zigbee_device(

zigbee_test_utils.prepare_zigbee_env_info()
local function test_init()
local SUPPORTED_ALARM_VALUES = { "damaged", "forcedOpeningAttempt", "unableToLockTheDoor", "notClosedForALongTime",
"highTemperature", "attemptsExceeded" }
test.socket.capability:__expect_send(mock_device:generate_test_message("main",
lockAlarm.supportedAlarmValues(SUPPORTED_ALARM_VALUES, { visibility = { displayed = false } })))
test.mock_device.add_test_device(mock_device)
end
test.set_test_init_function(test_init)
Expand Down
15 changes: 15 additions & 0 deletions drivers/SmartThings/matter-sensor/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,21 @@ matterManufacturer:
vendorId: 0x120B
productId: 0x1031
deviceProfileName: contact-battery
- id: "4619/4102"
deviceLabel: Heiman Smoke Sensor
vendorId: 0x120B
productId: 0x1006
deviceProfileName: smoke
- id: "4619/4098"
deviceLabel: Heiman CO Sensor
vendorId: 0x120B
productId: 0x1002
deviceProfileName: co-comeas
- id: "4619/4099"
deviceLabel: Heiman Smoke Sensor
vendorId: 0x120B
productId: 0x1003
deviceProfileName: smoke
# Legrand
- id: "Legrand/Netatmo/Smart-2-in-1-Sensor"
deviceLabel: Netatmo Smart 2-in-1 Sensor
Expand Down
11 changes: 11 additions & 0 deletions drivers/SmartThings/matter-switch/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ matterManufacturer:
vendorId: 0x1407
productId: 0x1088
deviceProfileName: light-color-level-illuminance-motion-1000K-15000K
#ELEGRP
- id: "5158/3"
deviceLabel: ELEGRP Smart Mini Plug
vendorId: 0x1426
productId: 0x0003
deviceProfileName: plug-binary
#Eve
- id: "Eve/Energy/US"
deviceLabel: Eve Energy
Expand Down Expand Up @@ -201,6 +207,11 @@ matterManufacturer:
vendorId: 0x1021
productId: 0x0007
deviceProfileName: plug-binary
- id: "4129/5"
deviceLabel: Radiant Smart Switch
vendorId: 0x1021
productId: 0x0005
deviceProfileName: switch-binary
#Lifx
- id: "5155/169"
deviceLabel: LIFX Color (A21)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ end

local function noop_event_emitter(device, ...)
local label = (device and device.label) or "Unknown Device Name"
local device_type = (device and device:get_field(Fields.DEVICE_TYPE)) or "Unknown Device Type"
local device_type = (device and utils.determine_device_type(device)) or "Unknown Device Type"
log.warn(string.format("Tried to find attribute event emitter for device [%s] of unsupported type [%s], ignoring", label, device_type))
end

Expand Down
2 changes: 1 addition & 1 deletion drivers/SmartThings/philips-hue/src/handlers/commands.lua
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ local refresh_handlers = require "handlers.refresh_handlers"
---@param cmd table?
---@return table? refreshed_device_info
function CommandHandlers.refresh_handler(driver, device, cmd)
return refresh_handlers.handler_for_device_type(device:get_field(Fields.DEVICE_TYPE))(driver, device, cmd)
return refresh_handlers.handler_for_device_type(utils.determine_device_type(device))(driver, device, cmd)
end

return CommandHandlers
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ local LifecycleHandlers = {}
---@param device HueDevice
---@param ... any arguments for device specific handler
function LifecycleHandlers.device_init(driver, device, ...)
local device_type = device:get_field(Fields.DEVICE_TYPE)
local device_type = utils.determine_device_type(device)
log.info(
string.format
("device_init for device %s, device_type: %s", (device.label or device.id or "unknown device"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ function RefreshHandlers.do_refresh_all_for_bridge(driver, bridge_device)

local statuses_by_device_type = {}
for _, device in ipairs(child_devices) do
local device_type = device:get_field(Fields.DEVICE_TYPE)
local device_type = utils.determine_device_type(device)
-- Query for the states of all devices for a device type for a given child device,
-- but only the first time we encounter a device type. We cache them since we're refreshing
-- everything.
Expand Down Expand Up @@ -359,7 +359,7 @@ end

local function noop_refresh_handler(driver, device, ...)
local label = (device and device.label) or "Unknown Device Name"
local device_type = (device and device:get_field(Fields.DEVICE_TYPE)) or "Unknown Device Type"
local device_type = (device and utils.determine_device_type(device)) or "Unknown Device Type"
log.warn(string.format("Received Refresh capability for unknown device [%s] type [%s], ignoring", label, device_type))
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ local utils = require "utils"
---@param device HueDevice
local function _remove(driver, device)
driver.datastore.dni_to_device_id[device.device_network_id] = nil
if device:get_field(Fields.DEVICE_TYPE) == "bridge" then
if utils.determine_device_type(device) == "bridge" then
local api_instance = device:get_field(Fields.BRIDGE_API) --[[@as PhilipsHueApi]]
if api_instance then
api_instance:shutdown()
Expand Down
6 changes: 4 additions & 2 deletions drivers/SmartThings/philips-hue/src/stray_device_helper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ function StrayDeviceHelper.spawn()
maybe_bridge:get_field(Fields.BRIDGE_API) --[[@as PhilipsHueApi]]
or Discovery.disco_api_instances[maybe_bridge.device_network_id]

if not api_instance then
if not api_instance and bridge_ip then
api_instance = HueApi.new_bridge_manager(
"https://" .. bridge_ip,
maybe_bridge:get_field(HueApi.APPLICATION_KEY_HEADER),
Expand All @@ -258,7 +258,9 @@ function StrayDeviceHelper.spawn()
Discovery.disco_api_instances[maybe_bridge.device_network_id] = api_instance
end

StrayDeviceHelper.process_strays(thread_local_driver, stray_devices, maybe_bridge.id)
if api_instance then
StrayDeviceHelper.process_strays(thread_local_driver, stray_devices, maybe_bridge.id)
end
end
end
end
Expand Down
1 change: 1 addition & 0 deletions drivers/SmartThings/philips-hue/src/utils/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ function utils.lazy_handler_loader(parent_module)
{},
{
__index = function(tbl, key)
if key == nil then return nil end
if nils[key] then return nil end
if rawget(tbl, key) == nil then
local success, mod = pcall(require, string.format("%s.%s", parent_module, key))
Expand Down
54 changes: 54 additions & 0 deletions drivers/SmartThings/zwave-switch/fingerprints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,60 @@ zwaveManufacturer:
productId: 0x0088
productType: 0x0002
deviceProfileName: smartplug-switch-power-energy
- id: 1120/2/129
deviceLabel: Wave 2PM 1
manufacturerId: 0x0460
productId: 0x0081
productType: 0x0002
deviceProfileName: metering-switch
- id: 1120/2/131
deviceLabel: Wave 1
manufacturerId: 0x0460
productId: 0x0083
productType: 0x0002
deviceProfileName: switch-binary
- id: 1120/2/132
deviceLabel: Wave 1PM
manufacturerId: 0x0460
productId: 0x0084
productType: 0x0002
deviceProfileName: metering-switch
- id: 1120/2/138
deviceLabel: Wave Pro 1
manufacturerId: 0x0460
productId: 0x008A
productType: 0x0002
deviceProfileName: switch-binary
- id: 1120/2/139
deviceLabel: Wave Pro 1PM
manufacturerId: 0x0460
productId: 0x008B
productType: 0x0002
deviceProfileName: metering-switch
- id: 1120/2/140
deviceLabel: Wave Pro 2 1
manufacturerId: 0x0460
productId: 0x008C
productType: 0x0002
deviceProfileName: switch-binary
- id: 1120/2/141
deviceLabel: Wave Pro 2PM 1
manufacturerId: 0x0460
productId: 0x008D
productType: 0x0002
deviceProfileName: metering-switch
- id: 1120/2/142
deviceLabel: Wave 1 Mini
manufacturerId: 0x0460
productId: 0x008E
productType: 0x0002
deviceProfileName: switch-binary
- id: 1120/2/143
deviceLabel: Wave 1PM Mini
manufacturerId: 0x0460
productId: 0x008F
productType: 0x0002
deviceProfileName: metering-switch
zwaveGeneric:
- id: "GenericSwitch/1"
deviceLabel: Switch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ local MULTI_METERING_SWITCH_FINGERPRINTS = {
{mfr = 0x015F, prod = 0x3102, model = 0x0204}, -- WYFY Touch 4-button Switch
{mfr = 0x015F, prod = 0x3111, model = 0x5102}, -- WYFY Touch 1-button Switch
{mfr = 0x015F, prod = 0x3121, model = 0x5102}, -- WYFY Touch 2-button Switch
{mfr = 0x015F, prod = 0x3141, model = 0x5102} -- WYFY Touch 4-button Switch
{mfr = 0x015F, prod = 0x3141, model = 0x5102}, -- WYFY Touch 4-button Switch
{mfr = 0x0460, prod = 0x0002, model = 0x0081}, -- Shelly Wave 2PM
{mfr = 0x0460, prod = 0x0002, model = 0x008C}, -- Shelly Wave Pro 2
{mfr = 0x0460, prod = 0x0002, model = 0x008D}, -- Shelly Wave Pro 2PM
}

local function can_handle_multi_metering_switch(opts, driver, device, ...)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,29 @@ local devices = {
CONFIGURATION = {
child_switch_device_profile = "switch-binary"
}
}
},
SHELLY_WAVE_2PM_AND_PRO = {
MATCHING_MATRIX = {
mfrs = 0x0460,
product_ids = {0x0081, 0x008D},
product_types = 0x0002,
children = 1
},
CONFIGURATION = {
child_switch_device_profile = "metering-switch"
}
},
SHELLY_WAVE_PRO_2 = {
MATCHING_MATRIX = {
mfrs = 0x0460,
product_ids = 0x008C,
product_types = 0x0002,
children = 1
},
CONFIGURATION = {
child_switch_device_profile = "switch-binary"
}
},
}

local multi_metering_switch_configurations = {}
Expand Down
Loading
Loading