Degree days calculation in Domoticz

Moderator: leecollings

Post Reply
HvdW
Posts: 539
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

Degree days calculation in Domoticz

Post by HvdW »

This post about degree days triggered me.
So I looked arpound on the internet and found this site about degree days from ehoco.
The publication is back dated where it uses a script to query WeatherUnderground.

Today Domoticz makes life easy for us.
Instead of Weatherunderground you can install the Buienradar, Accuweather. Meteoroligisk Institute Norway (YR) or Open Weather Map.
When set up these display (amongst others) Wind which shows your outside temperature.
This is important to calculate degree days.
Here is a script to extract temperature from the Wind tile.

Code: Select all

return 
{
	on = { devices = { 'KNMI Wind' }},
	
	execute = function(dz, item)
	    dz.devices('Buitentemperatuur').updateTemperature(item.temperature)
	end
}
We just need Buitentemperatuur - Outside temperature.
Of course you will have to create a virtual sensor Buitentemperatuur (Outside temperature) first.

From here on we can preceed with the script shown on ehoco's site.

Code: Select all

return {
    active = true,
    on = {
	    devices = {'Buitentemperatuur',}
	},

    logging = {
        level = domoticz.LOG_DEBUG,
        marker = 'gemiddelde temperatuur',
    },

	data = {
		temperatures = { history = true, maxHours = 24 },
	},
	
    execute = function(domoticz, sensor)
		-- add new data
		domoticz.data.temperatures.add(sensor.temperature)

		-- average
		local average = domoticz.data.temperatures.avg()
        domoticz.log('average temperature ' .. average, domoticz.LOG_INFO)
        domoticz.devices('Gem buitentemp').updateTemperature(average)
        domoticz.log('average temperature ' .. average, domoticz.LOG_INFO)

    end
} 
Adapt the script like the name of your own sensor and off you go.
Of course you will have to create a virtual sensor Gemiddelde temperatuur (Average temperature) first.
After that there is a script to fill the degree days icon with data.

Code: Select all

return { 
	on = { timer = { "at 23:59"}}, 
	
	execute = function(domoticz)
		local Date = domoticz.time.year..domoticz.time.month..domoticz.time.day
		local meantempOutside = domoticz.devices('Gem buitentemp').temperature
		local baseTemp = 18
		local factor = 1
		local degreesday = baseTemp - meantempOutside
		if (domoticz.time.month >= 4 and domoticz.time.month <= 9) then factor = 0.8 end
		if (domoticz.time.month >= 11 or domoticz.time.month <= 2) then factor = 1.1 end
		degreesdays = degreesday * factor
		local GasUsage = domoticz.devices('Gas').counterToday
		local GasUsageperDegreesday = domoticz.utils.round((GasUsage / degreesdays),3)
		if (degreesday <= 0) then
			degreesdays = 0
			GasUsageperDegreesday = 0
			GaspriceperDegreesday = 0
		end

		domoticz.log('Gemiddelde temperatuur buiten (laatste 24u): '..meantempOutside)
		domoticz.log('Gasverbruik vandaag: '..GasUsage..' m3')
		domoticz.log('Aantal graaddagen: '..degreesdays)
		domoticz.log('Gasverbruik per graaddag: '..GasUsageperDegreesday..' m3 per graaddag')

		domoticz.devices('Gas/graaddag').updateCustomSensor(GasUsageperDegreesday)
	end
}
Of course you will have to create a virtual sensor degree days first.
In the script I introduces a lot of other sensors.
Anyway it's fun to program it in dzvents.

Enjoy and ask if things are unclear.

EDIT
Removed some clutter to make the code better readable
Last edited by HvdW on Thursday 14 December 2023 12:24, edited 2 times in total.
Bugs bug me.
User avatar
waltervl
Posts: 5397
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: Degree days calculation in Domoticz

Post by waltervl »

I am not sure what you want to achieve. But you are aware that every temperature sensor shows its degree days value in the report page, per year and month?
Screenshot_20231213-234059-034.png
Screenshot_20231213-234059-034.png (104.34 KiB) Viewed 1635 times
Also in settings you can set the temperature from what you want to calculate the degree days (default 18 degrees C) https://www.domoticz.com/wiki/Applicati ... emperature
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
HvdW
Posts: 539
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

Re: Degree days calculation in Domoticz

Post by HvdW »

If one knows everything vantevoren one can go round the world with a dubbeltje.
Thanks for pointing this out @waltervl
There is a lot to learn indeed.
Desalniettemin I enjoyed the vingeroefeningen in dzvents programming.

Is there a json to view the degree days?
There is still a bit too do weighing the degree days.

BTW
As you can read from the code the script calculates weighted degree days.
Bugs bug me.
willemd
Posts: 630
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: Degree days calculation in Domoticz

Post by willemd »

For those that use gas:
I combined a similar degreeday calculation with another script to do gas classification, i.e. split my gas usage in gas used for heating, for hot water and for cooking. Initially the script was developed for my DSMR 4.0 meter, that reports gas usage per hour. Now I have adapted it for my DSMR 5.0 meter. It still relies on my OTGW to report when heating and/or hot water is switched on, measures gas during those seconds, and adds the quantity to the correct type of gas usage. After midnight the "heating gas per degreeday" is calculated in a 3rd script.

The gas_classification script is below. Sorry, not cleaned up after the switch from DSMR4 to DSMR5.

Code: Select all

--[[
This scrips classifies gas usage every hour into 3 different categories

This script first tracks the seconds during each hour that the hot water or central heating has been active.
If either hot water or central heating was active across the hour boundary then the seconds are split into before- and after-the-hour values,
because the P1 meter provides gas usage exactly before- and after-the-hour, even though the actual value of the previous hour is only
received a few minutes after the hour (between 02 and 04 minutes after the hour).
When the gas usage is received, the gas usage is split into the right categories using the known usage seconds of the past hour.
Any events between the hour and the gas usage update are tracked for the new hour.

Previous version of this script also included degreeday calculations, but these have now been removed because it did not work well. This is now in a separate script.

Known limitations:
- cooking gas is not measured separately so will also be included in heating or hot water gas, unless both were not active
- if both hot water and central heating were active, a theoretical split is made based on past known gas flow rate for hot water
(and this avg flow rate is updated if hot water usage has been longer than 3 minutes)
- gas value is known approx. 4 minutes after the hour from the P1 meter, it is the value for the previous hour. This requires some special handling.
- opentherm gateway updates the switch states only every 30 seconds.
- the script is especially made for a version 4 Smart Meter that provides a new gas value only once per hour

Note the script can be triggered in very quick succession if two switches are update almost simultaneously by the Opentherm Gateway
No problem has been observed as result of this.

The script has not been extensively tested during the heating season yet. Only 3 days so far ....

Note: don't use virtual GAS devices to track the types of gas usage. Use virtual COUNTER devices instead and update those manually (with edit device) to type GAS with divider 1000 once created.
This is because resets of GAS counters (not only counterToday but also counter) have been observed after midnight, (update 04/10/2022 : this problem seems to be solved in latest beta version)
 ]]--
 
local idxGasP1=2                 -- idx of P1 meter Gas usage
local idxCentralHeatingActive=50 -- idx of CH-enabled from Opentherm Gateway (because CH-active is actually CH-pump-active and therefore not the one to use)
local idxHotWaterActive=57       -- idx of HW-active from Opentherm Gateway
local idxFlame=58                -- idx of Flame On from Opentherm Gateway (used for small corrections when hot water usage is only a few seconds)

local idxCentralHeatingGas=87    -- 3 virtual devices for tracking type of GAS usage
local idxCookingGas=88
local idxHotWaterGas=89 

local idxAvgGasFlowRateHW=81     -- average hot water flow rate

return {
	on = {
		devices = {
			idxHotWaterActive, 			-- hw switch
			idxCentralHeatingActive,    -- ch switch
			idxGasP1                    -- GAS P1 update
		},
		timer = {
		    'every 5 minutes'  -- to split the seconds into past and future hour for any devices active at xx:00
		},    
	},
	data = {
	        -- persistent variables, values kept from one script run to the other, also after system reset
	        -- two variables for tracking how many seconds either hot water or central heating was switched ON during the hour
            hotwaterseconds = { initial = 0 },
            centralheatingseconds = { initial = 0 },
            -- a variable to check not only an update but an actual increase of the gas meter
            previousgascounter = { initial = 0 },
            -- variables to help splitting total seconds into before and after the hour boundary
            previoushourhotwaterseconds = { initial = 0 },
            newhourhotwaterseconds = { initial = 0 },
            previoushourcentralheatingseconds = { initial = 0 },
            newhourcentralheatingseconds = { initial = 0 },
            previoushourprocessed = { initial = 'True' },
            firstgasupdateoftheday = { initial = 'False' }
    },        
	logging = {
		level = domoticz.LOG_ERROR,
		marker = 'gas usage classification',
	},
	execute = function(domoticz, item)

	    if item.isDevice then  -- triggered by one of the devices, not the timer
    	    if item.idx==idxHotWaterActive then  -- hot water switched on/off
    	        if item.state == 'On' then
    		        domoticz.log('Hot Water was switched On', domoticz.LOG_INFO)
    		        -- on rare occasions Flame On is detected shortly before Hot Water is On
    		        --if (domoticz.devices(idxFlame).state=='On' and domoticz.devices(idxCentralHeatingActive).state=="Off") then
    		        --    domoticz.log('Should add extra ' .. domoticz.devices(idxFlame).lastUpdate.secondsAgo .. 'hot water seconds because of earlier flame activation', domoticz.LOG_INFO) 
    		        --    if domoticz.data.previoushourprocessed == 'True' then 
    		        --        domoticz.log('Adding seconds to current hr', domoticz.LOG_INFO)
    		        --        domoticz.data.hotwaterseconds = domoticz.data.hotwaterseconds + domoticz.devices(idxFlame).lastUpdate.secondsAgo
    		        --    else
    		        --        domoticz.log('Saving seconds for next hr', domoticz.LOG_INFO)
    		        --        domoticz.data.newhourhotwaterseconds = domoticz.data.newhourhotwaterseconds + domoticz.devices(idxFlame).lastUpdate.secondsAgo
    		        --    end    
    		        --end
    		    else
    		        domoticz.log('Hot Water was switched Off', domoticz.LOG_INFO)
    		        domoticz.log('previoushourprocessed' .. domoticz.data.previoushourprocessed )
    		        if domoticz.data.previoushourprocessed == 'True' then 
    		            domoticz.log('Adding seconds to current hr', domoticz.LOG_INFO)
    		            domoticz.data.hotwaterseconds = domoticz.data.hotwaterseconds + item.lastUpdate.secondsAgo - domoticz.data.previoushourhotwaterseconds
    		        else
    		            domoticz.log('Saving seconds for next hr', domoticz.LOG_INFO)
    		            domoticz.data.newhourhotwaterseconds = domoticz.data.newhourhotwaterseconds + item.lastUpdate.secondsAgo - domoticz.data.previoushourhotwaterseconds
    		        end       
    		        domoticz.log('Current time hot water ' .. item.lastUpdate.secondsAgo - domoticz.data.previoushourhotwaterseconds .. ' seconds', domoticz.LOG_INFO)
    		        domoticz.log('Total time hot water ' .. domoticz.data.hotwaterseconds .. ' seconds', domoticz.LOG_INFO)
    		        domoticz.data.previoushourhotwaterseconds = 0
    		    end  
    		end    
    	    if item.idx==idxCentralHeatingActive then
    	        if item.state == 'On' then
    		        domoticz.log('Central Heating was switched On', domoticz.LOG_INFO)
    		    else
    		        domoticz.log('Central Heating was switched Off', domoticz.LOG_INFO)
        		    if domoticz.data.previoushourprocessed == 'True' then 	
        		        domoticz.log('Adding seconds to current hr', domoticz.LOG_INFO)
        		        domoticz.data.centralheatingseconds = domoticz.data.centralheatingseconds + item.lastUpdate.secondsAgo - domoticz.data.previoushourcentralheatingseconds
        		    else      
        		        domoticz.log('Saving seconds for next hr', domoticz.LOG_INFO)
    		            domoticz.data.newhourcentralheatingseconds = domoticz.data.newhourcentralheatingseconds + item.lastUpdate.secondsAgo - domoticz.data.previoushourcentralheatingseconds
    		        end    		        
    		        domoticz.log('Current time central heating ' .. item.lastUpdate.secondsAgo - domoticz.data.previoushourcentralheatingseconds .. ' seconds', domoticz.LOG_INFO)
    		        domoticz.log('Total time central heating ' .. domoticz.data.centralheatingseconds .. ' seconds', domoticz.LOG_INFO)
    		        domoticz.data.previoushourcentralheatingseconds = 0
    		    end     
    		end    
    		if item.idx==idxGasP1 then
    	        local currentGas = domoticz.devices(idxGasP1).counter
    	        local increasegas = 0
    	        local currentValue=0
    	        
    	        --if domoticz.data.previousgascounter > 200 then
    	        --     domoticz.data.previousgascounter=102.284
    	        --end     
  
    	        domoticz.log('Triggered by GASP1 with value ' .. currentGas, domoticz.LOG_INFO)
    	        domoticz.log('while previous GASP1    value ' .. domoticz.data.previousgascounter, domoticz.LOG_INFO)
    		    domoticz.log('Device ' .. item.name .. ' was updated', domoticz.LOG_INFO)
    		    domoticz.log('hotwaterseconds ' .. domoticz.data.hotwaterseconds .. ' ', domoticz.LOG_INFO)
    		    domoticz.log('previous hr hotwaterseconds ' .. domoticz.data.previoushourhotwaterseconds .. ' ', domoticz.LOG_INFO)
    		    domoticz.log('centralheatingseconds ' .. domoticz.data.centralheatingseconds .. ' ', domoticz.LOG_INFO)
    		    domoticz.log('previous hr centralheatingseconds ' .. domoticz.data.previoushourcentralheatingseconds .. ' ', domoticz.LOG_INFO)
    		    
    		    domoticz.log('Hot Water Gas counter value ' .. domoticz.devices(idxHotWaterGas).counter .. ' ', domoticz.LOG_INFO)
        		domoticz.log('Hot Water Gas counterToday value ' .. domoticz.devices(idxHotWaterGas).counterToday .. ' ', domoticz.LOG_INFO)
        		domoticz.log('Central Heating Gas counter ' .. domoticz.devices(idxCentralHeatingGas).counter .. ' ', domoticz.LOG_INFO)
        		domoticz.log('Cooking Gas counter ' .. domoticz.devices(idxCookingGas).counter .. ' ', domoticz.LOG_INFO)

        		--if domoticz.devices(idxHotWaterGas).counter==0 then
        		--    domoticz.notify('Error: hot water gas counter was reset to zero',domoticz.PRIORITY_NORMAL)
        		--end    

    		    if currentGas>domoticz.data.previousgascounter then -- not only an update but a real increase. This occurs max every hour, approx 4 minutes past the hour
    		        -- The increase is the real increase of the previous hour. The P1 meter does a real split exactly at the hour.
    		        increasegas = domoticz.utils.round(currentGas - domoticz.data.previousgascounter,3)
    		        domoticz.log('Current value of Device ' .. item.name .. currentGas .. 'm3', domoticz.LOG_INFO)
    		        domoticz.log('Previousgascounter ' .. domoticz.data.previousgascounter .. 'm3', domoticz.LOG_INFO)
    		        domoticz.log('Value of Device ' .. item.name .. ' has increased by ' .. increasegas .. 'm3', domoticz.LOG_INFO)
    		        if domoticz.data.hotwaterseconds>0 and domoticz.data.centralheatingseconds==0 then
    		            domoticz.log('Value of Device ' .. item.name .. ' has increased as result of hot water (+ possibly cooking) usage', domoticz.LOG_INFO)
                        currentValue=domoticz.devices(idxHotWaterGas).counter
                        domoticz.devices(idxHotWaterGas).updateCounter(increasegas*1000+currentValue*1000)  -- update value must be in dm3
                        -- also update the avg gas flow rate for hot water, provided minimum 3 minute flow
                        -- apply factor 1000 for accuracy/decimals
                        if domoticz.data.hotwaterseconds>=180 then
                            local flowrate=increasegas/domoticz.data.hotwaterseconds*1000
                            local pastflowrate=domoticz.devices(idxAvgGasFlowRateHW).sensorValue
                            if flowrate<=1.5 * pastflowrate then -- ignore too high value, as result of inclusion of cooking gas
                                domoticz.devices(idxAvgGasFlowRateHW).updateCustomSensor(domoticz.utils.round((pastflowrate*9+flowrate)/10,3))  -- new value weights only 10% on the total average
                                domoticz.log('flow rate past hour ' .. flowrate .. ' ', domoticz.LOG_INFO)
                                domoticz.log('flow rate pas avg ' .. pastflowrate .. ' ', domoticz.LOG_INFO)
                            end
                        end    
    		        elseif domoticz.data.hotwaterseconds==0 and domoticz.data.centralheatingseconds>0 then
    		            domoticz.log('Value of Device ' .. item.name .. ' has increased as result of central heating (+ possibly cooking) usage', domoticz.LOG_INFO)
    		            
    		            currentValue=domoticz.devices(idxCentralHeatingGas).counter
                        domoticz.devices(idxCentralHeatingGas).updateCounter(increasegas*1000+currentValue*1000)  -- update value must be in dm3
    		        elseif domoticz.data.hotwaterseconds==0 and domoticz.data.centralheatingseconds==0 then   
    		            domoticz.log('Value of Device ' .. item.name .. ' has increased as result of cooking usage', domoticz.LOG_INFO)
    		            currentValue=domoticz.devices(idxCookingGas).counter
                        domoticz.devices(idxCookingGas).updateCounter(increasegas*1000+currentValue*1000)  -- update value must be in dm3
    		        elseif domoticz.data.hotwaterseconds>0 and domoticz.data.centralheatingseconds>0 then 
    		            domoticz.log('Value of Device ' .. item.name .. ' has increased as result of combined usage', domoticz.LOG_INFO)
    		            -- make a theoretical split between hot water and central heating, ignore possible cooking usage
    		            -- local hotwatergasestimate = domoticz.data.hotwaterseconds * 0.02/60 -- if not good avg calculation is available then 0.02 m3 per minute was a good average based on past observations
    		            local hotwatergasestimate = domoticz.devices(idxAvgGasFlowRateHW).sensorValue * domoticz.data.hotwaterseconds / 1000 -- assume now a good avg is available, so use it.
    		            if hotwatergasestimate> increasegas then
    		                hotwatergasestimate=increasegas
    		                increasegas = 0
    		            else
    		                increasegas = increasegas - hotwatergasestimate
    		            end
    		            currentValue=domoticz.devices(idxCentralHeatingGas).counter
                        domoticz.devices(idxCentralHeatingGas).updateCounter(increasegas*1000+currentValue*1000)  -- update value must be in dm3
                        currentValue=domoticz.devices(idxHotWaterGas).counter
                        domoticz.devices(idxHotWaterGas).updateCounter(hotwatergasestimate*1000+currentValue*1000)  -- update value must be in dm3
    		        end   
    		        domoticz.data.hotwaterseconds=domoticz.data.newhourhotwaterseconds
    		        domoticz.data.centralheatingseconds=domoticz.data.newhourcentralheatingseconds
    		        domoticz.data.newhourhotwaterseconds=0
    		        domoticz.data.newhourcentralheatingseconds=0 
    		        domoticz.data.previousgascounter=currentGas
    		        domoticz.data.previoushourprocessed='True'
                else
    		        domoticz.log('Value of Device ' .. item.name .. ' has stayed the same', domoticz.LOG_INFO)
    		    end
    		end    
    	else -- triggered by the timer, not one of the devices    
    		-- the hourly timer is used to split the seconds for any switches than are ON across the hour limit
    		if domoticz.devices(idxHotWaterActive).state == 'On' then
    		    -- calculate as-if switched off/on at the hour
    		    domoticz.log('As-if Hot Water was switched Off', domoticz.LOG_INFO)
    		    domoticz.data.previoushourhotwaterseconds=domoticz.devices(idxHotWaterActive).lastUpdate.secondsAgo
    		    -- the above value is kept for later correction when the OFF switch occurs and then reset
    		    domoticz.data.hotwaterseconds = domoticz.data.hotwaterseconds + domoticz.data.previoushourhotwaterseconds
    		    domoticz.log('Extra before-hour hot water ' .. domoticz.data.previoushourhotwaterseconds .. ' seconds', domoticz.LOG_INFO)
    		    domoticz.log('Total time hot water ' .. domoticz.data.hotwaterseconds .. ' seconds', domoticz.LOG_INFO)
    		end
    		if domoticz.devices(idxCentralHeatingActive).state == 'On' then
    		    -- calculate as-if switched off/on at the hour
    		    domoticz.log('As-if Central Heating was switched Off', domoticz.LOG_INFO)
    		    domoticz.data.previoushourcentralheatingseconds=domoticz.devices(idxCentralHeatingActive).lastUpdate.secondsAgo
    		    -- the above value is kept for later correction when the OFF switch occurs and then reset
    		    domoticz.data.centralheatingseconds = domoticz.data.centralheatingseconds + domoticz.data.previoushourcentralheatingseconds
    		    domoticz.log('Extra before-hour central heating ' .. domoticz.data.previoushourcentralheatingseconds .. ' seconds', domoticz.LOG_INFO)
    		    domoticz.log('Total time central heating ' .. domoticz.data.centralheatingseconds .. ' seconds', domoticz.LOG_INFO)
    		end
    		-- previoushourprocessed is used to ensure the value of hotwaterseconds is kept until the gas increase of the previous hour has been processed
    		if domoticz.data.hotwaterseconds==0 and domoticz.data.centralheatingseconds==0 then
    		    domoticz.data.previoushourprocessed='True'
    		else
    		    if domoticz.data.previoushourprocessed=='True' then  -- only carry forward the hotwaterseconds one single hour, not more.
    		        domoticz.data.previoushourprocessed='False'
    		    else
    		        domoticz.data.previoushourprocessed='True'
    		    end      
    		end  

    		--if domoticz.time.hour==0 then
    		-- below updates were added because of a domoticz bug, which is apparently solved in latest beta as per 04/10/2022
		    local currentcountervalue=0
		    currentcountervalue=domoticz.devices(idxCentralHeatingGas).counter
		    domoticz.log('Updating CH counter to existing value ' .. currentcountervalue .. ' ', domoticz.LOG_INFO)
		    domoticz.devices(idxCentralHeatingGas).updateCounter(currentcountervalue*1000) -- update with 0 increase to prevent loosing real updates later
		    currentcountervalue=domoticz.devices(idxHotWaterGas).counter
		    domoticz.log('Updating HW counter to existing value ' .. currentcountervalue .. ' ', domoticz.LOG_INFO)
		    domoticz.devices(idxHotWaterGas).updateCounter(currentcountervalue*1000) -- update with 0 increase to prevent loosing real updates later
		    currentcountervalue=domoticz.devices(idxCookingGas).counter
		    domoticz.log('Updating C counter to existing value ' .. currentcountervalue .. ' ', domoticz.LOG_INFO)
		    domoticz.devices(idxCookingGas).updateCounter(currentcountervalue*1000) -- update with 0 increase to prevent loosing real updates later
    		--end    
		end    
	end
}


User avatar
waltervl
Posts: 5397
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: Degree days calculation in Domoticz

Post by waltervl »

HvdW wrote: Thursday 14 December 2023 0:30 Is there a json to view the degree days?
There is still a bit too do weighing the degree days.

BTW
As you can read from the code the script calculates weighted degree days.
No, there is no json to report these...
So ideally one would like to report energy consumption (gas, electricity) per month per degree days to compare months and years on energy usage.
It would be nice to have that in the energy device report page.

To do that in the settings there should be an existing temperature device set/selected that can be used to do the calculations.
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
Post Reply

Who is online

Users browsing this forum: No registered users and 0 guests