From Windy to Domoticz  [Solved]

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

Moderator: leecollings

Post Reply
javalin
Posts: 71
Joined: Tuesday 30 April 2019 16:06
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10717
Location: Portugal
Contact:

From Windy to Domoticz

Post by javalin »

Good Morning,

I am trying to create code to get data from 2 Windy wind stations to send it to 2 domoticz dummy wind devices in the same script. If I create 1 script independently for each WS there is no problem, it works. But with a single script I am not managing to update the last dummy wind device.

This is my code:

Code: Select all

local scriptVar = 'WindyStation'
return
{
    on =
    {
        timer =
        {
            'every 1 minutes',
        },
        httpResponses =
        {
            scriptVar,
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG,
        marker = 'WindyStation',
    },

    execute = function(dz, item)
        local dznumber = 0
        local urlData = 0
        local count = 0
        local controls = -- control table
        {
            {
                Rota = true,         -- conditions
                post ='https://node.windy.com/obs/measurement/v2/ad-LERT/7/1?',
                device = 644
            },
            {
                Faro = true, 
                post = 'https://node.windy.com/obs/measurement/v2/ad-LPFR/7/1?',
                device = 645
            },
        }

        local function post(getData)
            dz.openURL(
            {
                url = urlData,
                method = 'GET',
                callback = scriptVar, -- httpResponses above.
            })
        return
        end

        local function walkConditions(type)
            for key, value in ipairs(controls) do  
                if value[type] then 
                    urlData= value.post
                    post(getData)
                end            
            end
        end

        if item.isTimer then
            walkConditions('Rota')
            walkConditions('Faro')
        elseif item.json then
            for key, value in ipairs(controls) do
                 dznumber = value.device
            local rt = item.json.data.temp
            for _, rec in ipairs(rt) do
                count = count + 1
            end
            dz.log("number of records: "..count , dz.LOG_DEBUG )           
            local temperature = item.json.data.temp[count] - 273.15
            local windspeed = item.json.data.wind[count]
            local winddir = item.json.data.windDir[count]   
            --local windgust = item.json.data.gust[count]  
            local wind_directionString = 0
            local c = 11.25
            if winddir <= 0 + c then
                wind_directionString = "N"
            elseif winddir <= 22.5 + c then 
                wind_directionString = "NNE"
            elseif winddir <= 45 + c then
                wind_directionString = "NE"
            elseif winddir <= 67.5 + c then
                wind_directionString = "ENE"
            elseif winddir <= 90 + c then
                wind_directionString = "E"
            elseif winddir <= 112.5 + c then
                wind_directionString = "ESE"
            elseif winddir <= 135 + c then
                wind_directionString = "SE"
            elseif winddir <= 157.5 + c then
                wind_directionString = "SSE"
            elseif winddir <= 180 + c then
                wind_directionString = "S"
            elseif winddir <= 202.5 + c then
                wind_directionString = "SSW"
            elseif winddir <= 225 + c then
                wind_directionString = "SW"
            elseif winddir <= 247.5 + c then
                wind_directionString = "WSW"
            elseif winddir <= 270 + c then
                wind_directionString = "W"
            elseif winddir <= 292.5 + c then
                wind_directionString = "WNW"
            elseif winddir <= 315 + c then
                wind_directionString = "NW"
            else 
                wind_directionString = "NNW"
            end
            local wind = dz.devices(dznumber)
            wind.updateWind(winddir, wind_directionString,windspeed,0,temperature,0)
            dz.log("temperature: "..temperature .."ºC" , dz.LOG_DEBUG )
            dz.log("wind: "..windspeed * 1.94 .."knots" , dz.LOG_DEBUG) 
            dz.log("winddir: "..winddir .."º" , dz.LOG_DEBUG) 
            end
        end
end
}
This is the log:

Code: Select all

2021-03-09 09:29:00.270 Status: dzVents: Info: WindyStation: ------ Start internal script: windy_stations2:, trigger: "every 1 minutes"
2021-03-09 09:29:00.270 Status: dzVents: Debug: WindyStation: OpenURL: url = https://node.windy.com/obs/measurement/v2/ad-LERT/7/1?
2021-03-09 09:29:00.270 Status: dzVents: Debug: WindyStation: OpenURL: method = GET
2021-03-09 09:29:00.270 Status: dzVents: Debug: WindyStation: OpenURL: post data = nil
2021-03-09 09:29:00.271 Status: dzVents: Debug: WindyStation: OpenURL: headers = nil
2021-03-09 09:29:00.271 Status: dzVents: Debug: WindyStation: OpenURL: callback = WindyStation
2021-03-09 09:29:00.271 Status: dzVents: Debug: WindyStation: OpenURL: url = https://node.windy.com/obs/measurement/v2/ad-LPFR/7/1?
2021-03-09 09:29:00.271 Status: dzVents: Debug: WindyStation: OpenURL: method = GET
2021-03-09 09:29:00.271 Status: dzVents: Debug: WindyStation: OpenURL: post data = nil
2021-03-09 09:29:00.271 Status: dzVents: Debug: WindyStation: OpenURL: headers = nil
2021-03-09 09:29:00.271 Status: dzVents: Debug: WindyStation: OpenURL: callback = WindyStation
2021-03-09 09:29:00.271 Status: dzVents: Info: WindyStation: ------ Finished windy_stations2
2021-03-09 09:29:01.203 Status: dzVents: Info: WindyStation: ------ Start internal script: windy_stations2: HTTPResponse: "WindyStation"
2021-03-09 09:29:01.264 Status: dzVents: Debug: WindyStation: number of records: 351
2021-03-09 09:29:01.279 Status: dzVents: Debug: WindyStation: Processing device-adapter for Rota LERT: Wind device adapter
2021-03-09 09:29:01.280 Status: dzVents: Debug: WindyStation: temperature: 11.0ºC
2021-03-09 09:29:01.280 Status: dzVents: Debug: WindyStation: wind: 3.88knots
2021-03-09 09:29:01.280 Status: dzVents: Debug: WindyStation: winddir: 60º
2021-03-09 09:29:01.280 Status: dzVents: Debug: WindyStation: number of records: 702
2021-03-09 09:29:01.280 Status: dzVents: Info: WindyStation: ------ Finished windy_stations2
2021-03-09 09:29:01.526 Status: dzVents: Info: WindyStation: ------ Start internal script: windy_stations2: HTTPResponse: "WindyStation"
2021-03-09 09:29:01.581 Status: dzVents: Debug: WindyStation: number of records: 347
2021-03-09 09:29:01.582 Status: dzVents: Info: WindyStation: ------ Finished windy_stations2
2021-03-09 09:29:01.280 Error: dzVents: Error: (3.1.1) WindyStation: An error occurred when calling event handler windy_stations2
2021-03-09 09:29:01.280 Error: dzVents: Error: (3.1.1) WindyStation: ...cz/scripts/dzVents/generated_scripts/windy_stations2.lua:74: attempt to perform arithmetic on a nil value (field '?')
2021-03-09 09:29:01.582 Error: dzVents: Error: (3.1.1) WindyStation: An error occurred when calling event handler windy_stations2
2021-03-09 09:29:01.582 Error: dzVents: Error: (3.1.1) WindyStation: ...cz/scripts/dzVents/generated_scripts/windy_stations2.lua:80: attempt to compare nil with number
At the moment the script send data to the first dummy wind device (idx=644). Problem is how send data to the second dummy wind device.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: From Windy to Domoticz

Post by waaren »

javalin wrote: Tuesday 09 March 2021 10:35 I am trying to create code to get data from 2 Windy wind stations to send it to 2 domoticz dummy wind devices in the same script. If I create 1 script independently for each WS there is no problem, it works. But with a single script I am not managing to update the last dummy wind device.
Can you try this one?

Code: Select all


local scriptVar = 'WindyStation'
return
{
    on =
    {
        timer =
        {
            'every 1 minutes',
        },
        httpResponses =
        {
            scriptVar .. '*',
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG,
        marker = 'WindyStation',
    },

    execute = function(dz, item)

       local controls = -- control table
        {
            {
                Rota = true,         -- conditions
                post ='https://node.windy.com/obs/measurement/v2/ad-LERT/7/1?',
                device = 644,
            },
            {
                Faro = true,
                post = 'https://node.windy.com/obs/measurement/v2/ad-LPFR/7/1?',
                device = 645,
            },
        }

        local function post(url, id)
            dz.openURL(
            {
                url = url,
                callback = scriptVar .. '_' .. id, -- httpResponses above.
            })
        end

        local function walkConditions(type)
            for key, value in ipairs(controls) do
                if value[type] then
                    post(value.post, value.device)
                end
            end
        end

        local function windDirection( nDir )
            windDirections = { 'N', 'NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW' , 'N'}
            return ( windDirections[ math.floor(  ( nDir + 11.25 ) / 22.50 ) + 1 ] )
        end

        if item.isTimer then
            walkConditions('Rota')
            walkConditions('Faro')

        elseif item.json then
              local idxStr = item.trigger:gsub(scriptVar ..'_', '')
            local idx = tonumber(idxStr)
            dz.log('Values for device ' .. idx ,dz.LOG_DEBUG )

            local temperature = item.json.data.temp[#item.json.data.temp] - 273.15
            local windspeed = item.json.data.wind[#item.json.data.wind]
            local winddir = item.json.data.windDir[#item.json.data.windDir]
            -- local windgust = item.json.data.gust[#item.json.data.gust]

            dz.devices(idx).updateWind(winddir, windDirection(winddir),windspeed,0,temperature,0)

            dz.log('temperature: '..temperature ..' ºC' , dz.LOG_DEBUG )
            dz.log('wind: '..windspeed * 1.94 ..' knots' , dz.LOG_DEBUG)
            dz.log('winddir: '..winddir ..' º' , dz.LOG_DEBUG)
            dz.log('winddir: '.. windDirection(winddir) , dz.LOG_DEBUG)

        else
            dz.log('problem with return', dz.LOG_ERROR)
            dz.log(item, dz.LOG_DEBUG)
        end
end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
javalin
Posts: 71
Joined: Tuesday 30 April 2019 16:06
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10717
Location: Portugal
Contact:

Re: From Windy to Domoticz

Post by javalin »

Can you try this one?
Thank you waaren, it works.

Code: Select all

local function windDirection( nDir )
windDirections = { 'N', 'NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW' , 'N'}
return ( windDirections[ math.floor(  ( nDir + 11.25 ) / 22.50 ) + 1 ] )
end
The beatiful way to get the cardinal point, I would never have thought of dividing the compass rose into 16 parts to extract the cardinal point. Simply brilliant

Code: Select all

local idxStr = item.trigger:gsub(scriptVar ..'_', '')
So idx device is part of the Callback and this is the solution to store the 'idx device' when script is executed by the httpResponse?

Code: Select all

local winddir = item.json.data.windDir[#item.json.data.windDir]
For some strange reason and only in one of the wind stations #item.json.data.windDir does not get the total number of recordings, I have taken a look to the json windDir table and it has several null records, this may be the reason. Temperature, wind and windDir json tables have the same number of records so I have changed the line to:

Code: Select all

local winddir = item.json.data.windDir[#item.json.data.temp]
and fixed the issue.
AllesVanZelf
Posts: 265
Joined: Monday 05 February 2018 8:42
Target OS: Raspberry Pi / ODroid
Domoticz version: 12467
Location: Netherlands, near Haarlem
Contact:

Re: From Windy to Domoticz

Post by AllesVanZelf »

Hello Javalin,
This is wonderfull! Did you create a virtual text sensor for this? The idx'es?
Where did you find the hyperlink to this locations?

Edit: Yes already found it. I choose dummy type wind+temp+'gevoel'. And on the website choose a location and nearest weatherstations. :D
Thank you!
Domoticz 2020.1 (12230) on Raspberry Pi 3B with Raspian Buster. Besides Domoticz, Rpi is running Pi-Hole.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: From Windy to Domoticz

Post by waaren »

javalin wrote: Tuesday 09 March 2021 22:14

Code: Select all

local idxStr = item.trigger:gsub(scriptVar ..'_', '')
So idx device is part of the Callback and this is the solution to store the 'idx device' when script is executed by the httpResponse?
Yes. Attached to callback when send and extracted when callback returns

Code: Select all

local winddir = item.json.data.windDir[#item.json.data.windDir]

For some strange reason and only in one of the wind stations #item.json.data.windDir does not get the total number of recordings, I have taken a look to the json windDir table and it has several null records, this may be the reason. Temperature, wind and windDir json tables have the same number of records so I have changed the line to:

Code: Select all

local winddir = item.json.data.windDir[#item.json.data.temp]
and fixed the issue.
Is indeed caused by the null values which are translated by the JSON handler to nil, and thus making gaps in the array.
See below for a solution using the lodash library for Lua. This will do the job in a more robust way using the _.findlast method.

Code: Select all


local scriptVar = 'WindyStation'
return
{
    on =
    {
        timer =
        {
            'every 1 minutes',
        },
        httpResponses =
        {
            scriptVar .. '*',
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG,
        marker = 'WindyStation',
    },

    execute = function(dz, item)

        local _ = dz.utils._   -- lodash library for Lua

       local controls = -- control table
        {
            {
                Rota = true,         -- conditions
                post ='https://node.windy.com/obs/measurement/v2/ad-LERT/7/1?',
                device = 644,
            },
            {
                Faro = true,
                post = 'https://node.windy.com/obs/measurement/v2/ad-LPFR/7/1?',
                device = 645,
            },
        }

        local function post(url, id)
            dz.openURL(
            {
                url = url,
                callback = scriptVar .. '_' .. id, -- attach _id to the callback string
            })
        end

        local function walkConditions(type)
            for key, value in ipairs(controls) do
                if value[type] then
                    post(value.post, value.device)
                end
            end
        end

        local function windDirection( nDir )
            windDirections = { 'N', 'NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW' , 'N'}
            return ( windDirections[ math.floor(  ( nDir + 11.25 ) / 22.50 ) + 1 ] )
        end

        if item.isTimer then
            walkConditions('Rota')
            walkConditions('Faro')

        elseif item.json then
            local idxStr = item.trigger:gsub(scriptVar ..'_', '') -- extract idz from callback string
            local idx = tonumber(idxStr) -- must be numeric
            dz.log('Values for device ' .. idx ,dz.LOG_DEBUG )

            local temperature = _.findLast(item.json.data.temp) - 273.15 -- _.findLast function does return the last element of the array. See
            local windspeed = _.findLast(item.json.data.wind) -- https://htmlpreview.github.io/?https://github.com/rwaaren/lodash.lua/blob/master/doc/index.html#_.findLast
            local winddir = _.findLast(item.json.data.windDir)

            dz.devices(idx).updateWind(winddir, windDirection(winddir),windspeed,0,temperature,0)

            dz.log('temperature: '..temperature ..' ºC' , dz.LOG_DEBUG )
            dz.log('wind: '..windspeed * 1.94 ..' knots' , dz.LOG_DEBUG)
            dz.log('winddir: '..winddir ..' º' , dz.LOG_DEBUG)
            dz.log('winddir: '..windDirection(winddir) , dz.LOG_DEBUG)

        else
            dz.log('problem with return', dz.LOG_ERROR)
            dz.log(item, dz.LOG_DEBUG)
        end
end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
javalin
Posts: 71
Joined: Tuesday 30 April 2019 16:06
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10717
Location: Portugal
Contact:

Re: From Windy to Domoticz

Post by javalin »

This will do the job in a more robust way using the _.findlast method.
Thank you waaren, now it works even better. With the use of #tablename dummy wind device did not update when the wind speed or wind direction value was null. Now, with _.findlast method the wind device can update also to zero values.
AllesVanZelf
Posts: 265
Joined: Monday 05 February 2018 8:42
Target OS: Raspberry Pi / ODroid
Domoticz version: 12467
Location: Netherlands, near Haarlem
Contact:

Re: From Windy to Domoticz

Post by AllesVanZelf »

@Waaren and @javalin,
Is it possible to implement windgust?
It was mentioned in the first version and commented out.
And 'Wind chill' (/ gevoelstemperatuur)
Domoticz 2020.1 (12230) on Raspberry Pi 3B with Raspian Buster. Besides Domoticz, Rpi is running Pi-Hole.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: From Windy to Domoticz

Post by waaren »

AllesVanZelf wrote: Thursday 11 March 2021 10:54 Is it possible to implement windgust and 'Wind chill'
I guess so.
Can you give me the url where the windgust is part of the return so I can test? The Wind Chill is something I can calculate based on temperature and windspeed.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
AllesVanZelf
Posts: 265
Joined: Monday 05 February 2018 8:42
Target OS: Raspberry Pi / ODroid
Domoticz version: 12467
Location: Netherlands, near Haarlem
Contact:

Re: From Windy to Domoticz

Post by AllesVanZelf »

If I see this page: link to station schiphol, I find:

Code: Select all

gust	
0	null
..
11	null
12	10.8 
Thank you, that would be great.
Domoticz 2020.1 (12230) on Raspberry Pi 3B with Raspian Buster. Besides Domoticz, Rpi is running Pi-Hole.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: From Windy to Domoticz

Post by waaren »

AllesVanZelf wrote: Thursday 11 March 2021 11:16 If I see this page: link to station schiphol
Can you try this one?

Code: Select all



local scriptVar = 'WindyStation'
return
{
    on =
    {
        timer =
        {
            'every 5 minutes',
        },
        httpResponses =
        {
            scriptVar .. '*',
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG,
        marker = 'WindyStation',
    },

    execute = function(dz, item)

        local _ = dz.utils._   -- lodash library for Lua

       local controls = -- control table
        {
            Rota =
            {
                active = true,
                code = 'ad-LERT',
                device = 644,
            },
            Faro =
            {
                active = false,
                code = 'ad-LPFR',
                device = 645,
            },
            Schiphol =
            {
                active = true,
                code = 'ad-EHAM',
                device = 857,
            },
        }

        local function postURL(code, idx, name)
            dz.openURL(
            {
                url = 'https://node.windy.com/obs/measurement/v2/' .. code .. '/7/1?',
                callback = scriptVar .. '_' .. name .. '_' .. idx,
            })
        end

        local function getData()
            for name, airport  in pairs(controls) do
                if airport.active then
                    postURL(airport.code, airport.device, name)
                end
            end
        end

        local function windDirection( nDir )
            windDirections = { 'N', 'NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW' , 'N'}
            return ( windDirections[ math.floor(  ( nDir + 11.25 ) / 22.50 ) + 1 ] )
        end


        local function cWindChill(windSpeed, temperature)
            if temperature == nil then return 0     -- Should not happen
            elseif windSpeed == nil then return 0     -- Should not happen
            -- chill temperature cannot be calculated for these conditions
            elseif windSpeed < 1.3 or windSpeed > 49 or temperature < -46 or temperature > 17 then return temperature end
            return dz.utils.round(13.12 + (0.6215 * temperature) - (13.96 * windSpeed^0.16) + (0.4867 * temperature * windSpeed^0.16), 1)
        end

        if item.isTimer then
            getData()

        elseif item.json then
            local airport = item.trigger:match('%_(.-)%_') -- extract name from callback string
            local idxStr = item.trigger:match('%d*$') -- extract idx from callback string
            local idx = tonumber(idxStr) -- must be numeric

            dz.log('Values from '.. airport .. ' for device ' .. idx ,dz.LOG_DEBUG )

            local temperature = _.findLast(item.json.data.temp) -- _.findLast function does return the last element of the array. See
            local windspeed = _.findLast(item.json.data.wind) -- https://htmlpreview.github.io/?https://github.com/rwaaren/lodash.lua/blob/master/doc/index.html#_.findLast
            local winddir = _.findLast(item.json.data.windDir)
            local windgust = _.findLast(item.json.data.gust) or 0

            if temperature == nil or windspeed == nil or winddir == nil then
                dz.log('Problem in the data. Skipping this reading', dz.LOG_DEBUG )
                dz.log('temperature: ' .. tostring(temperature), dz.LOG_DEBUG )
                dz.log('windspeed: ' .. tostring(windspeed), dz.LOG_DEBUG )
                dz.log('winddir: ' .. tostring(winddir), dz.LOG_DEBUG )
                return
            end
            
            temperature = temperature - 273.15
            local windchill = cWindChill(windspeed, temperature)

            dz.devices(idx).updateWind(winddir, windDirection(winddir),windspeed,windgust,temperature,windchill)

            dz.log('temperature: ' .. temperature ..' ºC' , dz.LOG_DEBUG )
            dz.log('wind: ' .. windspeed * 1.94 ..' knots' , dz.LOG_DEBUG)
            dz.log('winddir: ' .. winddir ..'º' , dz.LOG_DEBUG)
            dz.log('winddir: ' .. windDirection(winddir) , dz.LOG_DEBUG)
            dz.log('windgust: ' .. dz.utils.round(( windgust or 0) * 1.94,2) ..' knots' , dz.LOG_DEBUG)
            dz.log('windchill: ' .. windchill .. ' ºC' , dz.LOG_DEBUG)


        else
            dz.log('problem with return', dz.LOG_ERROR)
            dz.log(item, dz.LOG_DEBUG)
        end
end
}
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
AllesVanZelf
Posts: 265
Joined: Monday 05 February 2018 8:42
Target OS: Raspberry Pi / ODroid
Domoticz version: 12467
Location: Netherlands, near Haarlem
Contact:

Re: From Windy to Domoticz  [Solved]

Post by AllesVanZelf »

Thanks again Waaren. This is working well!!!
Domoticz 2020.1 (12230) on Raspberry Pi 3B with Raspian Buster. Besides Domoticz, Rpi is running Pi-Hole.
AllesVanZelf
Posts: 265
Joined: Monday 05 February 2018 8:42
Target OS: Raspberry Pi / ODroid
Domoticz version: 12467
Location: Netherlands, near Haarlem
Contact:

Re: From Windy to Domoticz

Post by AllesVanZelf »

Hmm. It was working for a while, but now Temp is zero.
I have this error in the Log:

Code: Select all

Error: dzVents: Error: (3.1.5) WindyStation: ...scripts/dzVents/generated_scripts/Windy all Schiphol.lua:77: attempt to perform arithmetic on a nil value 
Temperature is not updated and this gives an error in calculation?
Domoticz 2020.1 (12230) on Raspberry Pi 3B with Raspian Buster. Besides Domoticz, Rpi is running Pi-Hole.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: From Windy to Domoticz

Post by waaren »

AllesVanZelf wrote: Thursday 11 March 2021 13:28 Hmm. It was working for a while, but now Temp is zero.
I have this error in the Log:

Code: Select all

Error: dzVents: Error: (3.1.5) WindyStation: ...scripts/dzVents/generated_scripts/Windy all Schiphol.lua:77: attempt to perform arithmetic on a nil value 
Probably a data problem. Will build some extra protection around it.
The error you posted mention line 77 but in the script I posted, line 77 only contains

Code: Select all

end 
So I assume you added or removed some lines. If you do that and post an error with a line number, please also post the complete modified script. That will help in identifying the issue
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
AllesVanZelf
Posts: 265
Joined: Monday 05 February 2018 8:42
Target OS: Raspberry Pi / ODroid
Domoticz version: 12467
Location: Netherlands, near Haarlem
Contact:

Re: From Windy to Domoticz

Post by AllesVanZelf »

Sorry about that. The script is:

Code: Select all

local scriptVar = 'WindyStation'
return
{
    on =
    {
        timer =
        {
            'every 1 minutes',
        },
        httpResponses =
        {
            scriptVar .. '*',
        },
    },

    logging =
    {
        level = domoticz.LOG_DEBUG,
        marker = 'WindyStation',
    },

    execute = function(dz, item)

        local _ = dz.utils._   -- lodash library for Lua

       local controls = -- control table
        {
            Schiphol =
            {
                active = true,
                code = 'ad-EHAM',
                device = 2367,
            },
            Rota =
            {
                active = true,
                code = 'ad-LERT',
                device = 2368,
            },
        }

        local function postURL(code, idx, name)
            dz.openURL(
            {
                url = 'https://node.windy.com/obs/measurement/v2/' .. code .. '/7/1?',
                callback = scriptVar .. '_' .. name .. '_' .. idx,
            })
        end

        local function getData()
            for name, airport  in pairs(controls) do
				if airport.active then
					postURL(airport.code, airport.device, name)
                end
            end
        end

        local function windDirection( nDir )
            windDirections = { 'N', 'NNE','NE','ENE','E','ESE','SE','SSE','S','SSW','SW','WSW','W','WNW','NW','NNW' , 'N'}
            return ( windDirections[ math.floor(  ( nDir + 11.25 ) / 22.50 ) + 1 ] )
        end


        local function cWindChill(windSpeed, temperature)
            if temperature == nil then return 0     -- Should not happen
            elseif windSpeed == nil then return 0     -- Should not happen
            -- chill temperature cannot be calculated for these conditions
            elseif windSpeed < 1.3 or windSpeed > 49 or temperature < -46 or temperature > 17 then return temperature end
            return dz.utils.round(13.12 + (0.6215 * temperature) - (13.96 * windSpeed^0.16) + (0.4867 * temperature * windSpeed^0.16), 1)
        end

        if item.isTimer then
            getData()

        elseif item.json then
            local airport = item.trigger:match('%_(.-)%_') -- extract name from callback string
            local idxStr = item.trigger:match('%d*$') -- extract idx from callback string
            local idx = tonumber(idxStr) -- must be numeric

            dz.log('Values from '.. airport .. ' for device ' .. idx ,dz.LOG_DEBUG )

            local temperature = _.findLast(item.json.data.temp) - 273.15  -- _.findLast function does return the last element of the array. See
            local windspeed = _.findLast(item.json.data.wind) -- https://htmlpreview.github.io/?https://github.com/rwaaren/lodash.lua/blob/master/doc/index.html#_.findLast
            local winddir = _.findLast(item.json.data.windDir)
            local windgust = _.findLast(item.json.data.gust) or 0

            local windchill = cWindChill(windspeed, temperature)

            dz.devices(idx).updateWind(winddir, windDirection(winddir),windspeed,windgust,temperature,windchill)

            dz.log('temperature: ' .. temperature ..' ºC' , dz.LOG_DEBUG )
            dz.log('wind: ' .. windspeed * 1.94 ..' knots' , dz.LOG_DEBUG)
            dz.log('winddir: ' .. winddir ..'º' , dz.LOG_DEBUG)
            dz.log('winddir: ' .. windDirection(winddir) , dz.LOG_DEBUG)
            dz.log('windgust: ' .. dz.utils.round(( windgust or 0) * 1.94,2) ..' knots' , dz.LOG_DEBUG)
            dz.log('windchill: ' .. windchill .. ' ºC' , dz.LOG_DEBUG)


        else
            dz.log('problem with return', dz.LOG_ERROR)
            dz.log(item, dz.LOG_DEBUG)
        end
end
}
and error log line:

Code: Select all

 Error: dzVents: Error: (3.1.5) WindyStation: ...scripts/dzVents/generated_scripts/Windy all Schiphol.lua:83: attempt to perform arithmetic on a nil value

Line 83 is:

Code: Select all

local temperature = _.findLast(item.json.data.temp) - 273.15  
Domoticz 2020.1 (12230) on Raspberry Pi 3B with Raspian Buster. Besides Domoticz, Rpi is running Pi-Hole.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: From Windy to Domoticz

Post by waaren »

AllesVanZelf wrote: Thursday 11 March 2021 13:43 and error log line:

Code: Select all

 Error: dzVents: Error: (3.1.5) WindyStation: ...scripts/dzVents/generated_scripts/Windy all Schiphol.lua:83: attempt to perform arithmetic on a nil value

Line 83 is:

Code: Select all

local temperature = _.findLast(item.json.data.temp) - 273.15  
OK. I updated the version (with some protection) in my earlier post.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
javalin
Posts: 71
Joined: Tuesday 30 April 2019 16:06
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10717
Location: Portugal
Contact:

Re: From Windy to Domoticz

Post by javalin »

Code: Select all

@Waaren and @javalin,
Is it possible to implement windgust? 
I had disable Wind Gust line because, before upgrade script with _.findlast method, the script 'froze' when got a nil value. Faro and Rota has not Wind Gust values but others stations may.

I have discovered that original source that Windy shows came from METAR.

https://www.aviationweather.gov/metar

So, other way to get json info is in link bellow:

https://www.aviationweather.gov/cgi-bin ... 6639315631

Wind info is in rawOb line: "GMME 111330Z 35008KT 310V010 8000 NSC 19/13 Q1025 NOSIG"
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: From Windy to Domoticz

Post by waaren »

javalin wrote: Thursday 11 March 2021 14:30 I had disable Wind Gust line because, before upgrade script with _.findlast method, the script 'froze' when got a nil value. Faro and Rota has not Wind Gust values but others stations may.
I understand and that's why I added the "or 0" to windgust. So if _.findLast returns nil, the script will not crash but will replace nil with 0. This will give the same result as the hardcoded 0 in the updateWind statement you used.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
AllesVanZelf
Posts: 265
Joined: Monday 05 February 2018 8:42
Target OS: Raspberry Pi / ODroid
Domoticz version: 12467
Location: Netherlands, near Haarlem
Contact:

Re: From Windy to Domoticz

Post by AllesVanZelf »

Thank you Waaren for all the effort you put into this!
Domoticz 2020.1 (12230) on Raspberry Pi 3B with Raspian Buster. Besides Domoticz, Rpi is running Pi-Hole.
javalin
Posts: 71
Joined: Tuesday 30 April 2019 16:06
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.10717
Location: Portugal
Contact:

Re: From Windy to Domoticz

Post by javalin »

I understand and that's why I added the "or 0" to windgust. So if _.findLast returns nil, the script will not crash but will replace nil with 0. This will give the same result as the hardcoded 0 in the updateWind statement you used.
Understood, thank you very much for the help waaren.

Today was the first day that I truly understood this message:

Code: Select all

attempt to perform arithmetic on a nil value
Sometimes, I don't understand what I read, no matter how much I repeat...
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest