PVOutput Python Script (emoncms.org > PVOutput)

For the past few months i’d been using the bash script kindly donated by @Bill.Thomson

To get my emoncms data up in to PVOutput to have an alternative view on things.

But I found that in my setup the bash script occasionally dropped out and sent zero watts (both solar and usage) to PVOutput.

So I decided to try and re-write the whole thing in Python. I’m only a hobbyist coder at best so this has taken a little time.

I’ve tried to add some logging as well as some error checking.

Running this new python script alongside the bash script i’ve found mine doesn’t drop out when the bash one does. So an improvement of sorts.

I also added new functionality to grab the current temperature from DarkSky and also the current sun angle based upon your latitude and longitude.

There are comments within the code and a description up top. Hopefully this can help people out getting this to work in their system.

I decided to pull the data from emoncms.org so that I could code this in my lunch hours. :wink:

I’m sure you could amend the code to talk to your local instance if required.

#!/usr/bin/env python

# pvoutput_upload.py
# Pulls Solar and Home use data from your emoncms.org account and squirts the data up to PVOutput
#
# This can run on any internet host running Python3 and you should schedule the script to run every 5 mins
# You may be able to change to talk to your internal emonpi instance if you don't want it to go external.
#
# */5 * * * * /usr/bin/python3 /home/PVOutput/pvoutput_upload.py
#
# 5 mins is the shortest time period you can send to PVO (in donation mode), otherwise its 15 mins if you don't have a donation PVO account
# https://forum.pvoutput.org/c/donation-features
#
# Based on your longtitude and latitude the script also pulls down current tempearture (from DarkSky) and uses Pysolar to calculate the current sun angle.
# Use a website like https://www.latlong.net/ to calculate your lon and lat
#
# Note: For DarkSky you'll need to apply for a free API key via https://darksky.net/dev
# Note: The script is sending the sun angle data to v6 in PVO which is normally reserved for Voltage.  But I do this so I see angle on the live displayed graph.
# 
# As well as needing Python 3 installed you'll need to install the following modules
# sudo pip3 install pysolar
# sudo pip3 install numpy
# sudo pip3 install pytz

import time
import datetime
import json
import requests

from pysolar.solar import *
from pytz import timezone

##############################################################

def get_darksky_weather():

  option_list = "?units=si&exclude=minutely,hourly,alerts,daily"
  url = 'https://api.darksky.net/forecast/%s/%s,%s?%s' % (darkskyapi,lat,lon,option_list)

  if DEBUG ==1:
    app_log.info(url)

   # Get the data from Dark Sky.
  try:
    response = requests.get(url)
    json_res = response.json()
  except requests.exceptions.RequestException as e:
    if DEBUG ==1:
        app_log.error(e)

  if response.status_code == 200:
    current_temp_fan = round(json_res['currently']['temperature'],1)
    current_temp_cel = round(((current_temp_fan - 32) / 1.8),1)

    #Round temperature to nearest 0.5 otherwise PVOutput graph is very shaky
    current_temp_cel= round(current_temp_cel * 2) / 2
  
  return (current_temp_cel)

##############################################################

def get_emoncms_data(FEED_ID):

  payload = {'id': FEED_ID, 'apikey': EMONPI_APIKEY, 'start': UNIX_MILLI_START, 'end': UNIX_MILLI_END, 'interval': INTERVAL}

  header = {'content-type': 'application/json'}

  try:
	  response = requests.get("http://emoncms.org/feed/data.json", params=payload, headers=header)
  except requests.exceptions.RequestException as e:
    if DEBUG ==1:
        app_log.error('Feed ID: %s', FEED_ID)
        app_log.error(e)

  if response.status_code == 200:
    str_response = response.content.decode("utf-8")
  
    if DEBUG ==1:
        app_log.info(str_response)
        app_log.info(response.url)

    mylist = json.loads(str_response)

    READING = 0
    COUNT = 1
    TOTAL = 0
    TEXT_VALUES = ''

    for x in mylist: 
      #print (COUNT,x)
      READING = (x[1])
      TOTAL = TOTAL + READING
      COUNT = COUNT + 1
      TEXT_VALUES = TEXT_VALUES + (str(int(READING))) + ', '

    #print ()
    COUNT = COUNT - 1
    #print (COUNT)
    #print (TOTAL)
    OUTPUT = (int(TOTAL/COUNT))
    #print (OUTPUT)

    if DEBUG ==1:
        app_log.info('Number of numbers pulled: %s', COUNT)

  else:
    OUTPUT = 0

  return (OUTPUT, TEXT_VALUES)

#########################################################################

# Stick 'Sun Angle' in V6 (Voltage)
# You could always change to v7 to stick it in extended parameters (another PVO donation mode feature)

def post_pvoutput(): # may raise exceptions
  url = 'https://pvoutput.org/service/r2/addstatus.jsp'
  headers = {
    'X-Pvoutput-SystemId': str(PVO_SYSID),
    'X-Pvoutput-Apikey': str(PVO_API)
  }
  params = {
    'd': DATE,
    't': TIME,
    'v2': SOLAR_GEN,
    'v4': HOME_USAGE,
    'v5': TEMP,
    'v6': ALTITUDE
  }
  app_log.info('posting data to pvoutput')
  resp = requests.post(url, headers=headers, data=params, timeout=10)
  if resp.status_code != 200:
    app_log.error(resp.status_code)
    app_log.error('pvoutput returned code %s', resp.status_code)
    app_log.error(resp.text)
  return


##########################################################################

def get_sun_angle():
    uk_tz = timezone('Europe/London')
    # find your timezone from here https://stackoverflow.com/questions/13866926/is-there-a-list-of-pytz-timezones

    ALTITUDE = round((get_altitude(lat, -lon, datetime.datetime.now(uk_tz))),2)
    if ALTITUDE < 0:
        ALTITUDE = 0

    return ALTITUDE

##########################################################################

import logging
from logging.handlers import RotatingFileHandler

log_formatter = logging.Formatter('%(asctime)s %(levelname)s %(funcName)s(%(lineno)d) %(message)s')

# Windows current directory
logFile = 'log.txt'

# Linux absolute path
#logFile = '/home/PVOutput/log.txt'

my_handler = RotatingFileHandler(logFile, mode='a', maxBytes=5*1024*1024, backupCount=2, encoding=None, delay=0)
my_handler.setFormatter(log_formatter)
my_handler.setLevel(logging.INFO)

app_log = logging.getLogger('root')
app_log.setLevel(logging.INFO)

app_log.addHandler(my_handler)

###################################################################################

DEBUG=1

# PVOutput.org details
PVO_API='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' #your PVOutput.org API key
#PVO_SYSID='99999' # your PVOutput.org system ID
PVO_SYSID='99999' # Testing ID

# EmonCMS.org details
EMONPI_APIKEY='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
FEED_ID_USE=999999
FEED_ID_SOLAR=399999

# How many seconds between data points 
# (ie, EmonCMS updates every 10 seconds and PVOuput only accepts every 5 mins.... so using 10 seems to catch most of the 29/30 unique values)
INTERVAL=10

# DarkSky API details
lat = 99.4032481162862
lon = -10.52260641495603
darkskyapi = 'xxxxxxxxxxxxxxxxxxxxxx'

# Time right now in milliseconds
UNIX_MILLI_END=int(round(time.time() * 1000))
# 5 minutes ago in milliseconds (PVOutput only accepts 5 minute updates)
UNIX_MILLI_START=((UNIX_MILLI_END-300000))
# If you need to change this to 15 mins then its 900,000


# Date for PVOutput Use* conda install openssl
DATE = time.strftime('%Y%m%d')
TIME = time.strftime('%R')

#print (UNIX_MILLI_START)
#print (UNIX_MILLI_END)

# Reset working variables
SOLAR_GEN = 0
HOME_USAGE = 0
TEMP = 0

# Get Current Angle of the Sun
ALTITUDE=get_sun_angle()
if DEBUG ==1:
    app_log.info('Solar Altitude %s', ALTITUDE)

# Get Home Usage figure from EmonCMS API
FEED_ID = FEED_ID_USE 
HOME_USAGE, TEXT_VALUES = get_emoncms_data(FEED_ID)
if DEBUG ==1:
    app_log.info('Home Usage Raw %s', TEXT_VALUES)
#print (TEXT_VALUES)

# Get Solar Generation figure from EmonCMS API
FEED_ID = FEED_ID_SOLAR
SOLAR_GEN, TEXT_VALUES = get_emoncms_data(FEED_ID)
if DEBUG ==1:
    app_log.info('Solar Usage Raw %s', TEXT_VALUES)
#print (TEXT_VALUES)

# Get temperature from DarkSky API
TEMP = get_darksky_weather()

#print ()
#print (DATE)
#print (TIME)
#print ()
#print ('Solar: ',SOLAR_GEN)
#print ('Usage: ',HOME_USAGE)
#print ('Temp: ',TEMP)


app_log.info('Solar %s', SOLAR_GEN)
app_log.info('Usage: %s', HOME_USAGE)
app_log.info('Temp: %s', TEMP)
app_log.info('Solar Altitude: %s', ALTITUDE)


# Punt collected data up to PVPoutput.org
post_pvoutput()

pvout.zip (2.9 KB)

Edit - zipped and attached file. BT - moderator

1 Like

Nice work! thumbsup

I rewrote it entirely in Python, but as I use a Modbus based meter, I didn’t post the update.
(Figured it would be of little use to anyone not using Modbus)

2 Likes

This is just what I have been looking to do - many thanks for posting it.
My problem is that I have no experience with coding, so have been trying to teach myself to use python so I can use this on my system - I’m struggling somewhat, but making some small progress, however I’m hoping you could help me with an error I can’t work out?
When I try to run the program I get this error:
File “/Users/xxxxx/pvout2.py”, line 197, in
HOME_USAGE, TEXT_VALUES = get_emoncms_data(FEED_ID)

File “/Users/xxxxx/pvout2.py”, line 92, in get_emoncms_data
TOTAL = TOTAL + READING

TypeError: unsupported operand type(s) for +: ‘int’ and ‘str’

Any help would be much appreciated,
Cheers
Andrew

Hi Andrew,

Welcome aboard!

That error is telling you that you’re trying to add a string to an integer.

Ref:

I’m definitely not a Python expert, however in the first problem, that multiple assignment
seems to be getting emonCMS data, but I can’t see from the context whether a string or a number is expected. I think you’ll have to put some debugging statements in to determine what the intention was.

In the second case, is the problem not in the line above READING = (x[1])? It looks as if READING is expected to be a number, is x[1] a number? If not, you will get the error. Maybe it needs conversion from a string to a number?

The person who can really clear this up is @Zarch (no relation, as far as I know!).

I’ve made a few changes since that earlier version… see if this is any better.

 #!/usr/bin/env python

# pvoutput_upload.py
# Pulls Solar and Home use data from your emoncms.org account and squirts the data up to PVOutput
#
# This can run on any internet host running Python3 and you should schedule the script to run every 5 mins
# You may be able to change to talk to your internal emonpi instance if you don't want it to go external.
#
# */5 * * * * /usr/bin/python3 /home/PVOutput/pvoutput_upload.py
#
# 5 mins is the shortest time period you can send to PVO (in donation mode), otherwise its 15 mins if you don't have a donation PVO account
# https://forum.pvoutput.org/c/donation-features
#
# Based on your longtitude and latitude the script also pulls down current tempearture (from DarkSky) and uses Pysolar to calculate the current sun angle.
# Use a website like https://www.latlong.net/ to calculate your lon and lat
#
# Note: For DarkSky you'll need to apply for a free API key via https://darksky.net/dev
# Note: The script is sending the sun angle data to v6 in PVO which is normally reserved for Voltage.  But I do this so I see angle on the live displayed graph.
# 
# As well as needing Python 3 installed you'll need to install the following modules
# sudo pip3 install pysolar
# sudo pip3 install numpy
# sudo pip3 install pytz

import time
import datetime
import json
import requests
import platform
import sys

from pysolar.solar import *
from pytz import timezone

##############################################################

def get_darksky_weather():

  option_list = "?units=si&exclude=minutely,hourly,alerts,daily"
  url = 'https://api.darksky.net/forecast/%s/%s,%s?%s' % (darkskyapi,lat,lon,option_list)

  if DEBUG ==1:
    app_log.info(url)

   # Get the data from Dark Sky.
  try:
    response = requests.get(url)
    json_res = response.json()
  except requests.exceptions.RequestException as e:
    if DEBUG ==1:
        app_log.error(e)

  if response.status_code == 200:
    current_temp_fan = round(json_res['currently']['temperature'],1)
    current_temp_cel = round(((current_temp_fan - 32) / 1.8),1)

    cloud_cover = (json_res['currently']['cloudCover'])

    #Round temperature to nearest 0.5 otherwise PVOutput graph is very shaky
    current_temp_cel= round(current_temp_cel * 2) / 2
  
  return (current_temp_cel, cloud_cover)

##############################################################

def get_emoncms_data(FEED_ID):

  payload = {'id': FEED_ID, 'apikey': EMONPI_APIKEY, 'start': UNIX_MILLI_START, 'end': UNIX_MILLI_END, 'interval': INTERVAL}

  header = {'content-type': 'application/json'}

  try:
	  response = requests.get("http://emoncms.org/feed/data.json", params=payload, headers=header)
  except requests.exceptions.RequestException as e:
    if DEBUG ==1:
        app_log.error('Feed ID: %s', FEED_ID)
        app_log.error(e)

  if response.status_code == 200:
    str_response = response.content.decode("utf-8")
  
    if DEBUG ==1:
        app_log.info(str_response)
        app_log.info(response.url)

    mylist = json.loads(str_response)

    READING = 0
    COUNT = 1
    TOTAL = 0
    TEXT_VALUES = ''

    for x in mylist: 
      #print (COUNT,x)
      READING = (x[1])
      TOTAL = TOTAL + READING
      COUNT = COUNT + 1
      TEXT_VALUES = TEXT_VALUES + (str(int(READING))) + ', '

    #print ()
    COUNT = COUNT - 1
    #print (COUNT)
    #print (TOTAL)
    #OUTPUT = (int(TOTAL/COUNT))
    #print (OUTPUT)


    app_log.info('Number of numbers pulled (COUNT): %s', COUNT)
    app_log.info('Number of numbers (TOTAL): %s', TOTAL)

    if COUNT != 0 or TOTAL != 0:
      OUTPUT = (int(TOTAL/COUNT))
    else:
      OUTPUT = 0

  else:
    OUTPUT = 0

  return (OUTPUT, TEXT_VALUES)

#########################################################################

# Stick 'Sun Angle' in V6 (Voltage)
# You could always change to v7 to stick it in extended parameters (another PVO donation mode feature)

def post_pvoutput(): # may raise exceptions
  url = 'https://pvoutput.org/service/r2/addstatus.jsp'
  headers = {
    'X-Pvoutput-SystemId': str(PVO_SYSID),
    'X-Pvoutput-Apikey': str(PVO_API)
  }
  params = {
    'd': DATE,
    't': TIME,
    'v2': SOLAR_GEN,
    'v4': HOME_USAGE,
    'v5': TEMP,
    'v7': SOLAR_GEN,
    'v8': CLOUD_COVER,
    'v9': ALTITUDE,
    'v10': HOME_USAGE,
    'v11': IRRIDATION,
    'v12': AZIMUTH
  }

  app_log.info('posting data to pvoutput')
  resp = requests.post(url, headers=headers, data=params, timeout=10)
  if resp.status_code != 200:
    app_log.error(resp.status_code)
    app_log.error('pvoutput returned code %s', resp.status_code)
    app_log.error(resp.text)
  return


##########################################################################

def get_sun_angle():
    uk_tz = timezone('Europe/London')
    # find your timezone from here https://stackoverflow.com/questions/13866926/is-there-a-list-of-pytz-timezones

    ALTITUDE = round(get_altitude(lat, -lon, datetime.datetime.now(uk_tz)),2)
    app_log.info('Raw Sun Angle: %s', ALTITUDE)

    if ALTITUDE < 0:
        ALTITUDE = 0

    AZIMUTH = round(get_azimuth(lat, -lon, datetime.datetime.now(uk_tz)),2)
    app_log.info('Raw Sun Azimuth: %s', AZIMUTH)

    return ALTITUDE,AZIMUTH

##########################################################################

def get_sun_irridation():
    uk_tz = timezone('Europe/London')
    IRRIDATION = round((radiation.get_radiation_direct(datetime.datetime.now(uk_tz),ALTITUDE)),2)
    
    return IRRIDATION

##########################################################################

import logging
from logging.handlers import RotatingFileHandler

log_formatter = logging.Formatter('%(asctime)s %(levelname)s %(funcName)s(%(lineno)d) %(message)s')

if platform.system() == 'Windows':
  # Windows current directory
  logFile = 'log.txt'
else:
  # Linux absolute path
  logFile = '/home/sa_cs1mjwi/PVOutput/log.txt'

my_handler = RotatingFileHandler(logFile, mode='a', maxBytes=5*1024*1024, backupCount=2, encoding=None, delay=0)
my_handler.setFormatter(log_formatter)
my_handler.setLevel(logging.INFO)

app_log = logging.getLogger('root')
app_log.setLevel(logging.INFO)

app_log.addHandler(my_handler)

app_log.info('-----------------------------------------------------------------------------------------------------------------------------')
app_log.info('logfile: %s', logFile)

###################################################################################

DEBUG=1

# PVOutput.org details
PVO_API='1af248abxxxxxx0238d1d8b3690f9' #your PVOutput.org API key
PVO_SYSID='58xx7' # your PVOutput.org system ID
#PVO_SYSID='6xx43' # Testing ID

# EmonCMS.org details
EMONPI_APIKEY='08f04xx4d0cde56b43a2b'
FEED_ID_USE=3746xx
FEED_ID_SOLAR=3746xx

# How many seconds between data points 
# (ie, EmonCMS updates every 10 seconds and PVOuput only accepts every 5 mins.... so using 10 seems to catch most of the 29/30 unique values)
INTERVAL=10

# DarkSky API details
lat = 53.403248116xxx
lon = -1.5226064149xxxx
darkskyapi = '83da9xxxxxx283ffb9b9cc73dfc05ef55d'

# Time right now in milliseconds
UNIX_MILLI_END=int(round(time.time() * 1000))
# 5 minutes ago in milliseconds (PVOutput only accepts 5 minute updates)
UNIX_MILLI_START=((UNIX_MILLI_END-300000))
# If you need to change this to 15 mins then its 900,000


# Date for PVOutput Use* conda install openssl
DATE = time.strftime('%Y%m%d')
TIME = time.strftime('%R')

#print (UNIX_MILLI_START)
#print (UNIX_MILLI_END)

# Reset working variables
SOLAR_GEN = 0
HOME_USAGE = 0
TEMP = 0
ALTITUDE = 0
AZIMUTH = 0
IRRIDATION = 0
CLOUD_COVER = 0


# Get Current Angle of the Sun
ALTITUDE, AZIMUTH = get_sun_angle()
if DEBUG ==1:
    app_log.info('Sun Angle: %s', ALTITUDE)

# Get clear sky radiation of the Sun
IRRIDATION=get_sun_irridation()
if DEBUG ==1:
    app_log.info('Sun Irridation: %s', IRRIDATION)

# Get Home Usage figure from EmonCMS API
FEED_ID = FEED_ID_USE 
app_log.info('Getting Home Use, feed id: %s', FEED_ID)
HOME_USAGE, TEXT_VALUES = get_emoncms_data(FEED_ID)
if DEBUG ==1:
    app_log.info('Home Usage Raw: %s', TEXT_VALUES)
#print (TEXT_VALUES)

# Get Solar Generation figure from EmonCMS API
FEED_ID = FEED_ID_SOLAR
app_log.info('Getting Solar Use, feed id: %s', FEED_ID)
SOLAR_GEN, TEXT_VALUES = get_emoncms_data(FEED_ID)
if DEBUG ==1:
    app_log.info('Solar Usage Raw: %s', TEXT_VALUES)
#print (TEXT_VALUES)

# Get temperature from DarkSky API
TEMP, CLOUD_COVER = get_darksky_weather()

#print ()
#print (DATE)
#print (TIME)
#print ()
#print ('Solar: ',SOLAR_GEN)
#print ('Usage: ',HOME_USAGE)
#print ('Temp: ',TEMP)


app_log.info('Solar W: %s', SOLAR_GEN)
app_log.info('Usage W: %s', HOME_USAGE)
app_log.info('Temp: %s', TEMP)
app_log.info('Cloud Cover: %s', CLOUD_COVER)
app_log.info('Sun Angle: %s', ALTITUDE)
app_log.info('Sun Irridation: %s', IRRIDATION)

if platform.system() == 'Windows':
  # Windows current directory
  app_log.info('i am on Windows, no uploading')
else:
  # Punt collected data up to PVPoutput.org
  post_pvoutput()

I would like some assistance with this script, it was working for years and my EmonPI dies and I had to rebuild it, I have recreated everything, but I am getting the following error. Come someone please assist

/usr/bin/python3 /home/pi/pvoutput.py
Traceback (most recent call last):
File “/home/pi/pvoutput.py”, line 266, in
HOME_USAGE, TEXT_VALUES = get_emoncms_data(FEED_ID)
File “/home/pi/pvoutput.py”, line 96, in get_emoncms_data
TOTAL = TOTAL + READING
TypeError: unsupported operand type(s) for +: ‘int’ and ‘NoneType’

Here is my logfile

2023-01-12 07:27:18,776 INFO (203) -----------------------------------------------------------------------------------------------------------------------------
2023-01-12 07:27:18,777 INFO (204) logfile: /home/pi/log.txt
2023-01-12 07:27:18,863 INFO get_sun_angle(162) Raw Sun Angle: 1.57
2023-01-12 07:27:18,871 INFO get_sun_angle(168) Raw Sun Azimuth: 114.34
2023-01-12 07:27:18,872 INFO (256) Sun Angle: 1.57
2023-01-12 07:27:18,873 INFO (261) Sun Irridation: 7.71
2023-01-12 07:27:18,873 INFO (265) Getting Home Use, feed id: 1
2023-01-12 07:27:18,900 INFO get_emoncms_data(83) [[1673508138000,617],[1673508148000,730],[1673508158000,730],[1673508168000,711],[1673508178000,711],[1673508188000,724],[1673508198000,724],[1673508208000,720],[1673508218000,720],[1673508228000,693],[1673508238000,693],[1673508248000,699],[1673508258000,699],[1673508268000,716],[1673508278000,716],[1673508288000,738],[1673508298000,738],[1673508308000,724],[1673508318000,724],[1673508328000,716],[1673508338000,716],[1673508348000,null],[1673508358000,null],[1673508368000,null],[1673508378000,null],[1673508388000,null],[1673508398000,null],[1673508408000,null],[1673508418000,null],[1673508428000,null],[1673508438000,null]]
2023-01-12 07:27:18,900 INFO get_emoncms_data(84) http://127.0.0.1/feed/data.json?id=1&apikey=xxxxxxxxxxxxxxxxxxxxxxxxxx&start=1673508138778&end=1673508438778&interval=10

@Zarch & @Robert.Wall The problem seems to be with the collection returning 1 value with a None

root@emonpi:/home/pi# /usr/bin/python3 /home/pi/pvoutput.py
1673512700844
1673513000844
1 [1673512700000, 1441]
1441
2 [1673512710000, 1441]
1441
3 [1673512720000, 1455]
1455
4 [1673512730000, 1455]
1455
5 [1673512740000, 1434]
1434
6 [1673512750000, 1434]
1434
7 [1673512760000, 1440]
1440
8 [1673512770000, 1440]
1440
9 [1673512780000, 1426]
1426
10 [1673512790000, 1426]
1426
11 [1673512800000, 1535]
1535
12 [1673512810000, 1535]
1535
13 [1673512820000, 1529]
1529
14 [1673512830000, 1529]
1529
15 [1673512840000, 1524]
1524
16 [1673512850000, None]
None
Traceback (most recent call last):
File “/home/pi/pvoutput.py”, line 270, in
HOME_USAGE, TEXT_VALUES = get_emoncms_data(FEED_ID)
File “/home/pi/pvoutput.py”, line 100, in get_emoncms_data
TOTAL = TOTAL + READING
TypeError: unsupported operand type(s) for +: ‘int’ and ‘NoneType’

Ok I have add a chekc at line 97 to check for a none type and procces line (98-100) if not detected,
This seems to have fixed the issue

  if READING is not None:
      TOTAL = TOTAL + READING
      COUNT = COUNT + 1
      TEXT_VALUES = TEXT_VALUES + (str(int(READING))) + ', '
1 Like

Dark Sky is end of life, is there an alternitive and can someone help update the script, maybe we can just disable the Darksky portion of the script ?

Try replcing

# Get temperature from DarkSky API
TEMP, CLOUD_COVER = get_darksky_weather()

with

TEMP = 0
CLOUD_COVER = 0

That should stop the call to dark sky and just put 0 into those values.

1 Like

Hi Zarch,
Thank you for the feed back, for some reason the python script was giving issue, like divide by zero and updates where missing from pvoutput.
for this reason I have since moved to this script

It works incrediably well and allows easy customization to add additiinal data,
Thanks for you help and support on the pvoutput.py script, I had used it for many years.