We have moved at community.getvera.com

Author Topic: find device id by search pattern  (Read 572 times)

Offline DesT

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +5/-1
find device id by search pattern
« on: January 27, 2019, 09:43:39 am »
Hey guys...

I'm sure I know I already see something about that somewhere but can't find it...

In my code I have somewhere a loop like..

local myDevices = {277,278,284,285,286,288,289,293,294,295,296,297,298,299,302,303,304,305,308,339,354,355,389,461,462,463,464,485,486,498}

for _,d in ipairs (myDevices) do
         do something here...
end

I need to replace my local myDevices = { something } with a function that will return all the ID of devices that match something in the "device name"

Is it something possible in Lua ?
Vera Edge-UI7/Plus-UI7 (2), DSC Partition (5 ) + Zones Sensors(31), Nest thermostat (1) & Protect Fire/CO (3), GE Sw (8 ), GE Dimr (14), FGMS-001 (2), ZW100 (2), RZCS4 (1), AL-DSC11 (1), Aeon HEM 2nd Edition (1), Aeon SSE (5), YRD220-ZW (1), SONOS (6), MyQ Chamberlain (1)
PINE64/openLuup/ALTUI/Rules

Offline rigpapa

  • Beta Testers
  • Hero Member
  • *****
  • Posts: 1121
  • Karma: +187/-3
Re: find device id by search pattern
« Reply #1 on: January 27, 2019, 09:49:27 am »
Code: [Select]
for _,d in ipairs (myDevices) do
    if luup.devices[d] and luup.devices[d].description:match( pattern ) then
        -- do what you need done, this device matches
    end
end

For patterns, see: https://www.lua.org/pil/20.2.html

EDIT: More complete example to answer the question:

Code: [Select]
function findDevices( pattern )
    local res = {} -- empty array to start
    for n,d in pairs( luup.devices ) do
        if d.description:match( pattern ) then
            table.insert( res, n )
        end
    end
    return res
end

This function returns an array (Lua table) of device numbers, the names of which match the pattern argument.
« Last Edit: January 27, 2019, 10:00:28 am by rigpapa »
Author of Reactor, DelayLight, SiteSensor, Rachio, Deus Ex Machina II, Intesis WMP Gateway, Auto Virtual Thermostat and VirtualSensor plugins. Vera Plus w/100+ Z-wave devices. Vera3, Lite. Hassio, Slapdash.

Offline DesT

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +5/-1
Re: find device id by search pattern
« Reply #2 on: January 27, 2019, 09:59:48 am »
Thanks man...
But in your code I still have to list my device ID in myDevices variable... is it possible to have a if that will check against all devices?  I would like to have a for loop with a more dynamic search so I never need to change my code.

Code: [Select]
for _,d in ipairs (myDevices) do
    if luup.devices[d] and luup.devices[d].description:match( pattern ) then
        -- do what you need done, this device matches
    end
end

For patterns, see: https://www.lua.org/pil/20.2.html
Vera Edge-UI7/Plus-UI7 (2), DSC Partition (5 ) + Zones Sensors(31), Nest thermostat (1) & Protect Fire/CO (3), GE Sw (8 ), GE Dimr (14), FGMS-001 (2), ZW100 (2), RZCS4 (1), AL-DSC11 (1), Aeon HEM 2nd Edition (1), Aeon SSE (5), YRD220-ZW (1), SONOS (6), MyQ Chamberlain (1)
PINE64/openLuup/ALTUI/Rules

Offline rigpapa

  • Beta Testers
  • Hero Member
  • *****
  • Posts: 1121
  • Karma: +187/-3
Re: find device id by search pattern
« Reply #3 on: January 27, 2019, 10:01:07 am »
Posted an edit to my response while you were answering. Check back on my previous answer--I think I've got you.
Author of Reactor, DelayLight, SiteSensor, Rachio, Deus Ex Machina II, Intesis WMP Gateway, Auto Virtual Thermostat and VirtualSensor plugins. Vera Plus w/100+ Z-wave devices. Vera3, Lite. Hassio, Slapdash.

Offline DesT

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +5/-1
Re: find device id by search pattern
« Reply #4 on: January 27, 2019, 10:08:35 am »
Thanks again ;)

Just modify my code with your new snippet and having something like that:

Code: [Select]
function findDevices( pattern )
    local res = {} -- empty array to start
    for n,d in pairs( luup.devices ) do
        if d.description:match( pattern ) then
            table.insert( res, n )
        end
    end
    return res
end

local myDevices = findDevices('SS:')

for _,d in ipairs (myDevices) do
    if luup.devices[d] and luup.devices[d].description:match( 'SS:' ) then
        print (myDevices)
    end
end

And looks like it's working perfectly ;)
Vera Edge-UI7/Plus-UI7 (2), DSC Partition (5 ) + Zones Sensors(31), Nest thermostat (1) & Protect Fire/CO (3), GE Sw (8 ), GE Dimr (14), FGMS-001 (2), ZW100 (2), RZCS4 (1), AL-DSC11 (1), Aeon HEM 2nd Edition (1), Aeon SSE (5), YRD220-ZW (1), SONOS (6), MyQ Chamberlain (1)
PINE64/openLuup/ALTUI/Rules

Offline rigpapa

  • Beta Testers
  • Hero Member
  • *****
  • Posts: 1121
  • Karma: +187/-3
Re: find device id by search pattern
« Reply #5 on: January 27, 2019, 10:19:46 am »
Thanks again ;)

Just modify my code with your new snippet and having something like that:

Code: [Select]
function findDevices( pattern )
    local res = {} -- empty array to start
    for n,d in pairs( luup.devices ) do
        if d.description:match( pattern ) then
            table.insert( res, n )
        end
    end
    return res
end

local myDevices = findDevices('SS:')

for _,d in ipairs (myDevices) do
    if luup.devices[d] and luup.devices[d].description:match( 'SS:' ) then
        print (myDevices)
    end
end

And looks like it's working perfectly ;)

With the function doing the pattern match, you don't need the pattern check in the second loop--that work is already done. The function returns only those devices that match the pattern. So now, you should be doing something more like:

Code: [Select]
...

local myDevices = findDevices('SS:')

for _,d in ipairs( myDevices ) do
    local devobj = luup.devices[d] -- for example, to access the device object for the current matching device
    -- Do something
    ...
end
« Last Edit: January 27, 2019, 10:21:41 am by rigpapa »
Author of Reactor, DelayLight, SiteSensor, Rachio, Deus Ex Machina II, Intesis WMP Gateway, Auto Virtual Thermostat and VirtualSensor plugins. Vera Plus w/100+ Z-wave devices. Vera3, Lite. Hassio, Slapdash.

Offline DesT

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +5/-1
Re: find device id by search pattern
« Reply #6 on: January 27, 2019, 10:25:35 am »
Ohh yeah.... my mistake.  You're right! ;)
Vera Edge-UI7/Plus-UI7 (2), DSC Partition (5 ) + Zones Sensors(31), Nest thermostat (1) & Protect Fire/CO (3), GE Sw (8 ), GE Dimr (14), FGMS-001 (2), ZW100 (2), RZCS4 (1), AL-DSC11 (1), Aeon HEM 2nd Edition (1), Aeon SSE (5), YRD220-ZW (1), SONOS (6), MyQ Chamberlain (1)
PINE64/openLuup/ALTUI/Rules

Offline akbooer

  • Moderator
  • Master Member
  • *****
  • Posts: 6387
  • Karma: +291/-70
  • "Less is more"
Re: find device id by search pattern
« Reply #7 on: January 27, 2019, 10:26:24 am »
It would be nice not to have to generate an array and then loop through that... which you can do with coroutines:

Code: [Select]
local function matchDev (pattern)
    local function match ()
        for n,d in pairs (luup.devices) do
            if d.description:match (pattern) then
                coroutine.yield (n,d)
            end
        end
    end
    return coroutine.wrap (match)
end   

Use this like:

Code: [Select]
for n,d in matchDev "SS:" do
    print (n, d.description)
end
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline rigpapa

  • Beta Testers
  • Hero Member
  • *****
  • Posts: 1121
  • Karma: +187/-3
Re: find device id by search pattern
« Reply #8 on: January 27, 2019, 10:49:37 am »
Sure, maybe a bit much for the new players. :) But if you're going that way, we can simplify a tiny bit because coroutines are not required...

Code: [Select]
function matchDev( pattern )
    local last = nil
    return function()
        while true do
            local d
            last,d = next( luup.devices, last )
            if not last or d.description:match( pattern ) then
                return last,d
            end
        end
    end
end

for n,d in matchDev('SS:') do
    ...
end
« Last Edit: January 27, 2019, 10:58:00 am by rigpapa »
Author of Reactor, DelayLight, SiteSensor, Rachio, Deus Ex Machina II, Intesis WMP Gateway, Auto Virtual Thermostat and VirtualSensor plugins. Vera Plus w/100+ Z-wave devices. Vera3, Lite. Hassio, Slapdash.

Offline DesT

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +5/-1
Re: find device id by search pattern
« Reply #9 on: January 27, 2019, 11:00:37 am »
Guys.... you are so awesome ;)

If we push that to another level again....

How to have a

function matchDev( pattern, room)

;)

EDIT:  I like a function that return the ID so I can use it anywhere else in a for loop.  I have a Tools functions file that I declare a bunch of function that I can use anywhere with Tools.mynewfunction
« Last Edit: January 27, 2019, 11:02:47 am by DesT »
Vera Edge-UI7/Plus-UI7 (2), DSC Partition (5 ) + Zones Sensors(31), Nest thermostat (1) & Protect Fire/CO (3), GE Sw (8 ), GE Dimr (14), FGMS-001 (2), ZW100 (2), RZCS4 (1), AL-DSC11 (1), Aeon HEM 2nd Edition (1), Aeon SSE (5), YRD220-ZW (1), SONOS (6), MyQ Chamberlain (1)
PINE64/openLuup/ALTUI/Rules

Offline akbooer

  • Moderator
  • Master Member
  • *****
  • Posts: 6387
  • Karma: +291/-70
  • "Less is more"
Re: find device id by search pattern
« Reply #10 on: January 27, 2019, 11:12:54 am »
How to have a

function matchDev( pattern, room)

Well, if you must...

Code: [Select]
function matchDev ( pattern , room)
    return function(_, last)
        while true do
            local d
            last,d = next( luup.devices, last )
            if not last or (d.description:match( pattern ) and (not room or room == d.room_num)) then
                return last,d
            end
        end
    end
end

The use of the room parameter is optional... it will work as before without it.
« Last Edit: January 27, 2019, 11:24:42 am by akbooer »
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.

Offline rigpapa

  • Beta Testers
  • Hero Member
  • *****
  • Posts: 1121
  • Karma: +187/-3
Re: find device id by search pattern
« Reply #11 on: January 27, 2019, 11:17:15 am »
And if you change the pattern match to: d.description:match( pattern or '.*' ) in either akbooers or mine, the pattern also becomes optional and matches all device names if nil, so you can specify either pattern, room, or both, and get expected results.
Author of Reactor, DelayLight, SiteSensor, Rachio, Deus Ex Machina II, Intesis WMP Gateway, Auto Virtual Thermostat and VirtualSensor plugins. Vera Plus w/100+ Z-wave devices. Vera3, Lite. Hassio, Slapdash.

Offline DesT

  • Sr. Member
  • ****
  • Posts: 364
  • Karma: +5/-1
Re: find device id by search pattern
« Reply #12 on: January 27, 2019, 11:33:03 am »
Playing with the last version of the code.. and I added the change of rigpapa for the description that give me:

Code: [Select]
function matchDev (pattern, room)
    return function(_, last)
        while true do
            local d
            last,d = next( luup.devices, last )
            if not last or (d.description:match( pattern or '.*' ) and (not room or room == d.room_num)) then
                return last,d
            end
        end
    end
end

and trying with

Code: [Select]
for n,d in Tools.matchDev('D-') do
    print(d)
end

or

Code: [Select]
for n,d in Tools.matchDev('D-','Basement') do
    print(d)
end

Not sure my search works very well...  and at the same time, what's the special character in pattern for tell START WITH "D-" ?  I check the link from rigpapa and can't find anything about that...
Vera Edge-UI7/Plus-UI7 (2), DSC Partition (5 ) + Zones Sensors(31), Nest thermostat (1) & Protect Fire/CO (3), GE Sw (8 ), GE Dimr (14), FGMS-001 (2), ZW100 (2), RZCS4 (1), AL-DSC11 (1), Aeon HEM 2nd Edition (1), Aeon SSE (5), YRD220-ZW (1), SONOS (6), MyQ Chamberlain (1)
PINE64/openLuup/ALTUI/Rules

Offline rigpapa

  • Beta Testers
  • Hero Member
  • *****
  • Posts: 1121
  • Karma: +187/-3
Re: find device id by search pattern
« Reply #13 on: January 27, 2019, 11:39:49 am »
The dash character is one of the special characters in a pattern, so you have to escape it, which for Lua patterns means putting a '%' in front of it. And to start a check from the beginning of the string, you use a caret, so in all "^D%-"

And your room needs to be an ID, not a name. By name is a whole new can of worms.
Author of Reactor, DelayLight, SiteSensor, Rachio, Deus Ex Machina II, Intesis WMP Gateway, Auto Virtual Thermostat and VirtualSensor plugins. Vera Plus w/100+ Z-wave devices. Vera3, Lite. Hassio, Slapdash.

Offline akbooer

  • Moderator
  • Master Member
  • *****
  • Posts: 6387
  • Karma: +291/-70
  • "Less is more"
Re: find device id by search pattern
« Reply #14 on: January 27, 2019, 11:41:36 am »
You have to be careful with search patterns, since severa lcharacters have special meanings.  '-' is one of them.  You need to quote it like this "D%-".

The special characters for 'starts with' is '^', so you'd need "^D%-".

The rooms are room numbers, not names, although the code could be changed.
3x Vera Lite-UI5/Edge-UI7, 25x Fibaro, 23x TKB, 9x MiniMote, 2x NorthQ Power, 2x Netatmo, 1x Foscam FI9831P, 9x Philips Hue,
Razberry, MySensors Arduino, HomeWave, AltUI, AltHue, DataYours, Grafana, openLuup, ZWay, ZeroBrane Studio.