[Ready to use] OpenWeatherMap - a new EMS Module that works without quering your Inverter
See original GitHub issueI have coded a EMS module that works without the need to access your inverter. It works by weather data from OpenWeatherMap and some fixed details about your solar installation.
This is my first step into python coding so Im sorry for mistakes on it. Also Im sure it can be improved a lot more and leave it open for others to jump in.
# OpenWeatherMap,py module for TWCManager by GMerg
import logging
logger = logging.getLogger(__name__.rsplit(".")[-1])
class OpenWeatherMap:
import requests
import time
cacheTime = 60
config = None
configConfig = None
configOpenWeatherMap = None
fetchFailed = False
generatedW = 0
consumedW = 0
lastFetch = 0
master = None
APIKey = None
Latitude = 0
Longitude = 0
status = False
timeout = 10
PeakKW = None
LastJson = None
def __init__(self, master):
self.master = master
self.config = master.config
try:
self.configConfig = master.config["config"]
except KeyError:
self.configConfig = {}
try:
self.configOpenWeatherMap = master.config["sources"]["OpenWeatherMap"]
except KeyError:
self.configOpenWeatherMap = {}
self.status = self.configOpenWeatherMap.get("enabled", False)
self.Latitude = self.configOpenWeatherMap.get("Latitude", 0)
self.Longitude = self.configOpenWeatherMap.get("Longitude", 0)
self.APIKey = self.configOpenWeatherMap.get("APIKey", None)
self.PeakKW = self.configOpenWeatherMap.get("PeakKW", None)
# Unload if this module is disabled or misconfigured
if (not self.status) or (not self.APIKey):
self.master.releaseModule("lib.TWCManager.EMS", "OpenWeatherMap")
return None
def getConsumption(self):
# since this is not knowing our consumption!
return 0;
def getGeneration(self):
if not self.status:
logger.debug("OpenWeatherMap EMS Module Disabled. Skipping getGeneration")
return 0
# Perform updates if necessary
self.update()
# Return generation value
if not self.generatedW:
self.generatedW = 0
return float(self.generatedW)
def getOpenWeatherMapData(self):
url = "https://api.openweathermap.org/data/2.5/onecall?lat=" + str(self.Latitude) + "&lon=" + str(self.Longitude) + "&appid=" + self.APIKey + "&exclude=minutely&units=metric"
return self.getOpenWeatherMapValue(url)
def getOpenWeatherMapValue(self, url):
# Fetch the specified URL from the OpenWeatherMap and return the data
self.fetchFailed = False
try:
r = self.requests.get(url, timeout=self.timeout)
except self.requests.exceptions.ConnectionError as e:
logger.log(
logging.INFO4,
"Error connecting to OpenWeatherMap to fetch sensor value",
)
logger.debug(str(e))
self.fetchFailed = True
return False
r.raise_for_status()
jsondata = r.json()
return jsondata
def getBestJsonSet(self, jsondata, dt):
#get the json data that matches best based on dt
bestjson=jsondata['current']
dif=abs(bestjson['dt']-dt)
for section in ['hourly', 'daily' ]:
for subset in jsondata[section]:
cmp = abs(subset['dt']-dt)
if (dif==0) or (cmp<dif):
dif=cmp
bestjson=subset
return bestjson
def update(self):
month = int(self.time.strftime("%m"))
dt = int(self.time.time())
if (int(self.time.time()) - self.lastFetch) > self.cacheTime:
# Cache has expired. Fetch values from OpenWeatherMap inverter.
tmp = self.getOpenWeatherMapData()
if tmp:
self.LastJson = tmp
# Update last fetch time
if self.fetchFailed is not True:
self.lastFetch = int(self.time.time())
if self.LastJson:
try:
subset = self.getBestJsonSet(self.LastJson,dt)
sunrise = self.LastJson['current']['sunrise']
sunset = self.LastJson['current']['sunset']
clouds = subset['clouds']
temp = subset['temp']
logger.info( "OpenWeatherMap response/subset: " + str(subset))
#it's night time!
if (dt < sunrise) or (dt > sunset):
self.generatedW=0
logger.info("OpenWeatherMap said it's Nighttime -> 0 kw")
else:
#modifier based on date time
midday = int( sunrise + ((sunset-sunrise)/2) )
if (dt < midday):
mod_day = (1/(midday-sunrise))*(dt-sunrise)
else:
mod_day = (1/(midday-sunrise))*(midday-(dt-midday)-sunrise)
if mod_day > 0.9:
mod_day = 1
elif mod_day < 0.2:
mod_day = 0.2
#modifier based on clouds, the /3 was done to improve results...cuz clouds with e.g. 70% almost always gave back 100% kw anyway
mod_cloud = 1-(clouds/100/3)
#a temperature above 87° fahrenheit (or 31° celsius) will reduce effeciency by 1% each degree
#at least thats what a paper suggested
if (temp > 31):
mod_temp = 1-((temp-31)/100)
if(mod_temp>0.5):
# limit this modification by 0.5 maximum
mod_temp=0.5
else:
mod_temp = 1
#other ideas...
#- reduce on snow
#- use uvi value to calculate another modifier...though needs monitoring a longer range
#- reduce on fog
#- use none linear sunrise/sunset -> midday but gausian algo here
self.generatedW = self.PeakKW[ month - 1 ] * mod_day * mod_cloud * mod_temp * 1000
logger.info("peak: "+str(self.PeakKW[ month - 1 ])+", mod_cloud: "+str(mod_cloud)+", mod_day:" +str(mod_day)+", mod_temp:"+str(mod_temp))
except (KeyError, TypeError) as e:
logger.log(
logging.INFO4, "Exception during parsing OpenWeatherMapData"
)
logger.debug(e)
return True
else:
# Cache time has not elapsed since last fetch, serve from cache.
return False
What you need to configure in /etc/twcmanager/config.json under sources…
"OpenWeatherMap": {
"enabled": true,
#your position on earth, use maps.google and copy from the URL parameters after the @ sign
"Latitude": 41.909986
"Longitude": 12.3959158,
#APIKey from https://openweathermap.org/
"APIKey": "xyz-EDIT-ME-xyz",
#a 12 items array with the best kW reached on a day in that month
"PeakKW": [2, 4, 6, 6, 6.5, 6.9, 6.5, 6.0, 5.5, 4.5, 3, 2]
}
Issue Analytics
- State:
- Created 2 years ago
- Comments:5 (2 by maintainers)
Top Results From Across the Web
How to start to work with Openweather API - OpenWeatherMap
It is quite easy to work with Openweather API. Just sign up to get your API key and then call any weather API....
Read more >Frequently Asked Questions - OpenWeatherMap
Get started · How to get an API key · What products and types of data can I request? · Do I need...
Read more >OpenWeatherMap API guide
The "OpenWeather API Guide" helps you find the list of weather products, useful information, links, and documentation to start using our weather API ......
Read more >Partners and solutions - OpenWeatherMap
It allows quick and easy consumption of OWM weather data (either observations and forecast) from Python applications via a simple object model. No...
Read more >Weather API - OpenWeatherMap
Please, sign up to use our fast and easy-to-work weather APIs. ... One Call API 3.0 NEW ... Read more about this API...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Let me show it with a sample… Graph: https://www.tesla.com/sites/default/files/support-images/solarpanels-production-app-homescreen.png You see it’s almost a perfect curve. And on noon it had almost 13kW peak. Thats the value you would use here, not the 91.2kWh. As that was for March, you would set the 3rd element to 13.
@ngardiner yes correct. This should be the value where no clouds are present and at midday…so basically the best value you can get on that day in that month. Thats just a suggestion…maybe there is a better way to do it but it worked pretty good for me.