Map one range of numbers to another

Easy to use, 100% Lua-based event scripting framework.

Moderator: leecollings

Post Reply
User avatar
RvdM
Posts: 39
Joined: Friday 10 July 2015 21:06
Target OS: Linux
Domoticz version: 2020.2 1
Location: Deventer, NL
Contact:

Map one range of numbers to another

Post by RvdM »

With C++ there is a map function which is able to map one range of numbers to another.
An example is like this:

Code: Select all

int percentage = map(300, 500, 0, 100);
300 equals 0 and 500 equals 100 which makes it easy to calculate things like for example percentages.
Is this possible with lua as well because I couldn't find such a function.
Running virtualized domoticz server on a proxmox cluster with a slave for optimal RFX communication. Using Aeotec Z-Stick Gen5, rfxtrx433e, Homebridge and a Philips HUE bridge for all sort of home automation.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Map one range of numbers to another

Post by waaren »

RvdM wrote: Sunday 23 May 2021 20:22 Is this possible with lua as well because I couldn't find such a function.
In Lua you can use a table to do that.

Code: Select all

local map =
{
	[300] = 0,
	[500] = 100,
}

print(map[300])
print(map[500])
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
User avatar
RvdM
Posts: 39
Joined: Friday 10 July 2015 21:06
Target OS: Linux
Domoticz version: 2020.2 1
Location: Deventer, NL
Contact:

Re: Map one range of numbers to another

Post by RvdM »

Perhaps i'm doing something wrong but this doesn't work.

Code: Select all

2021-05-23 21:22:00.479 Error: dzVents: Error: (3.1.8) test: ...v-domoticz/scripts/dzVents/generated_scripts/ScriptT.lua:25: attempt to concatenate a nil value (local 'test')

Code: Select all

return {
	active = {
		true,  
	},

	on = {
        timer = { 'every minute' }
    },

	logging = {
        level = domoticz.LOG_DEBUG,
        marker = "test"
    },

	execute = function(domoticz, triggeredItem, info)
		
	local map =
            {
	            [300] = 0,
	            [500] = 100,
            }

        local test = map[400]

        domoticz.log('test' .. test, LOG_DEBUG)

        domoticz.devices('TestCustomSensor').updateCustomSensor(test)

	end
}
Running virtualized domoticz server on a proxmox cluster with a slave for optimal RFX communication. Using Aeotec Z-Stick Gen5, rfxtrx433e, Homebridge and a Philips HUE bridge for all sort of home automation.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: Map one range of numbers to another

Post by waaren »

RvdM wrote:Perhaps i'm doing something wrong but this doesn't work.

Code: Select all

2021-05-23 21:22:00.479 Error: dzVents: Error: (3.1.8) test: ...v-domoticz/scripts/dzVents/generated_scripts/ScriptT.lua:25: attempt to concatenate a nil value (local 'test')
You defined 300 and 500 as keys and then try to call key 400?

or maybe you are looking for something like

Code: Select all


local tMap = { 300, 500, 0, 100 }

local function map(n, decimals)
	if n > tMap[2] or n < tMap[1] then return 'out of range' end -- protect range
	local integer = type(decimals) ~= 'number' 
	local decimals = decimals or 2 
	local result = ( n - tMap[1]) * (tMap[4] - tMap[3]) / (tMap[2] - tMap[1]) 
	return ( ( integer and domoticz.utils.round( result ) ) or ( round ( result, decimals ) ) ) -- rounded to integer or number of decimals
end

print(map(300)) -->> 0
print(map(400)) -->> 50
print(map(401.1357)) -->> 51
print(map(401.1357,4)) -->> 50.5678
print(map(500)) -->> 100

print(map(-299)) -->> out of range
print(map(501)) -->> out of range


Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
User avatar
RvdM
Posts: 39
Joined: Friday 10 July 2015 21:06
Target OS: Linux
Domoticz version: 2020.2 1
Location: Deventer, NL
Contact:

Re: Map one range of numbers to another

Post by RvdM »

Yes thats it.. but I still get an error

Code: Select all

2021-05-24 16:44:00.518 Error: dzVents: Error: (3.1.8) test: ...v-domoticz/scripts/dzVents/generated_scripts/ScriptT.lua:21: attempt to compare number with string

Code: Select all

	execute = function(domoticz, triggeredItem, info)
		
        local tMap = { 0, 48, 0, 100 }
    
        local function map(n, decimals)
    	    
    	    if n > tMap[2] or n < tMap[1] then return 'out of range' end -- protect range
    	        local integer = type(decimals) ~= 'number' 
    	        local decimals = decimals or 2 
    	        local result = ( n - tMap[1]) * (tMap[4] - tMap[3]) / (tMap[2] - tMap[1]) 
    	        return ( ( integer and domoticz.utils.round( result ) ) or ( round ( result, decimals ) ) ) -- rounded to integer or number of decimals
            end
    
            niveau = domoticz.devices('Plant - CrotonPetra - WaterNiveau').state
            local percentage = map(niveau)
    
            domoticz.devices('Plant - CrotonPetra - Percentage').updateCustomSensor(percentage)

	end
Running virtualized domoticz server on a proxmox cluster with a slave for optimal RFX communication. Using Aeotec Z-Stick Gen5, rfxtrx433e, Homebridge and a Philips HUE bridge for all sort of home automation.
User avatar
RvdM
Posts: 39
Joined: Friday 10 July 2015 21:06
Target OS: Linux
Domoticz version: 2020.2 1
Location: Deventer, NL
Contact:

Re: Map one range of numbers to another

Post by RvdM »

Solved

Code: Select all

            niveau = tonumber(domoticz.devices('Plant - CrotonPetra - WaterNiveau').state)
I also changed the function so it equals how the function in C++ works

Code: Select all

        local function map(n, w, x, y, z, decimals)
    	    if n > x or n < w then return 'out of range' end -- protect range
    	    local integer = type(decimals) ~= 'number' 
    	    local decimals = decimals or 2 
    	    local result = (n - w) * (z - y) / (x - w) 
    	    return ( ( integer and domoticz.utils.round( result ) ) or ( round ( result, decimals ) ) ) -- rounded to integer or number of decimals
        end
Running virtualized domoticz server on a proxmox cluster with a slave for optimal RFX communication. Using Aeotec Z-Stick Gen5, rfxtrx433e, Homebridge and a Philips HUE bridge for all sort of home automation.
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest