# PVOutput Python Script (emoncms.org \> PVOutput)

**URL:** <https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112>\
**Category:** Integrations\
**Created:** [15 February 2019 14:17 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112 "2019-02-15T14:17:30Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Zarch](https://community.openenergymonitor.org/user_avatar/community.openenergymonitor.org/zarch/32/7947_2.png) [@Zarch](https://community.openenergymonitor.org/u/Zarch)\
**Post date:** [15 February 2019 14:17 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112/1 "2019-02-15T14:17:30Z")

</div>

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

> [@PVOutput.org NodeRed](https://community.openenergymonitor.org/t/pvoutput-org-nodered/779/7):
>
> Hi Jeremy, Here’s what I use to send data from emonCMS to [PVOutput.org](http://PVOutput.org): #!/bin/bash PVO\_API='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' #your PVOutput.org API key PVO\_SYSID='xxxxx' # your PVOutput.org system ID FEED\_ID\_A='X' # id number of the feed you want to read data from FEED\_ID\_B='X' DATE=$(date "+%Y%m%d") TIME=$(date "+%H:%M") A=$(curl -s http://127.0.0.1/emoncms/feed/value.json?id=$FEED\_ID\_A) B=$(curl -s http://127.0.0.1/emoncms/feed/value.json?id=$FEED\_ID\_B) #A=$(wget -qO- http://1…

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](http://emoncms.org) so that I could code this in my lunch hours. 😉

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](https://community.openenergymonitor.org/uploads/default/original/2X/f/f3ea6f06e8a31dfcf08122a93c338591e6911e02.zip) (2.9 KB)

_Edit - zipped and attached file. BT - moderator_

---

<div class="post-metadata">

**Author:** ![Bill.Thomson](https://community.openenergymonitor.org/user_avatar/community.openenergymonitor.org/bill.thomson/32/1834_2.png) [@Bill.Thomson](https://community.openenergymonitor.org/u/Bill.Thomson)\
**Post date:** [15 February 2019 14:23 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112/2 "2019-02-15T14:23:16Z")

</div>

Nice work! ![thumbsup](https://community.openenergymonitor.org/uploads/default/original/2X/3/3c587556c0cc11389317c03a60788d77ceebd307.gif)

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)

---

<div class="post-metadata">

**Author:** ![aferguson](https://community.openenergymonitor.org/letter_avatar_proxy/v4/letter/a/7cd45c/32.png) [@aferguson](https://community.openenergymonitor.org/u/aferguson)\
**Post date:** [1 April 2019 16:25 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112/3 "2019-04-01T16:25:02Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![Bill.Thomson](https://community.openenergymonitor.org/user_avatar/community.openenergymonitor.org/bill.thomson/32/1834_2.png) [@Bill.Thomson](https://community.openenergymonitor.org/u/Bill.Thomson)\
**Post date:** [2 April 2019 14:29 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112/4 "2019-04-02T14:29:47Z")

</div>

Hi Andrew,

Welcome aboard!

> [@aferguson](#):
>
> TypeError: unsupported operand type(s) for +: ‘int’ and ‘str’

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

Ref:

> <https://stackoverflow.com/questions/20441035/unsupported-operand-types-for-int-and-str>

---

<div class="post-metadata">

**Author:** ![Robert.Wall](https://community.openenergymonitor.org/user_avatar/community.openenergymonitor.org/robert.wall/32/38246_2.png) [@Robert.Wall](https://community.openenergymonitor.org/u/Robert.Wall)\
**Post date:** [2 April 2019 15:08 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112/5 "2019-04-02T15:08:50Z")

</div>

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!).

---

<div class="post-metadata">

**Author:** ![Zarch](https://community.openenergymonitor.org/user_avatar/community.openenergymonitor.org/zarch/32/7947_2.png) [@Zarch](https://community.openenergymonitor.org/u/Zarch)\
**Post date:** [2 April 2019 20:24 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112/6 "2019-04-02T20:24:55Z")

</div>

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

```auto
 #!/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()
```

---

<div class="post-metadata">

**Author:** ![rolfbartels](https://community.openenergymonitor.org/letter_avatar_proxy/v4/letter/r/e0b2c6/32.png) [@rolfbartels](https://community.openenergymonitor.org/u/rolfbartels)\
**Post date:** [12 January 2023 07:33 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112/7 "2023-01-12T07:33:09Z")

</div>

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](http://127.0.0.1/feed/data.json?id=1&apikey=xxxxxxxxxxxxxxxxxxxxxxxxxx&start=1673508138778&end=1673508438778&interval=10)

---

<div class="post-metadata">

**Author:** ![rolfbartels](https://community.openenergymonitor.org/letter_avatar_proxy/v4/letter/r/e0b2c6/32.png) [@rolfbartels](https://community.openenergymonitor.org/u/rolfbartels)\
**Post date:** [12 January 2023 08:45 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112/8 "2023-01-12T08:45:01Z")

</div>

@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’

---

<div class="post-metadata">

**Author:** ![rolfbartels](https://community.openenergymonitor.org/letter_avatar_proxy/v4/letter/r/e0b2c6/32.png) [@rolfbartels](https://community.openenergymonitor.org/u/rolfbartels)\
**Post date:** [12 January 2023 08:56 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112/9 "2023-01-12T08:56:11Z")

</div>

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))) + ', '
> 
> ```

---

<div class="post-metadata">

**Author:** ![rolfbartels](https://community.openenergymonitor.org/letter_avatar_proxy/v4/letter/r/e0b2c6/32.png) [@rolfbartels](https://community.openenergymonitor.org/u/rolfbartels)\
**Post date:** [11 April 2023 21:46 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112/10 "2023-04-11T21:46:12Z")

</div>

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 ?

---

<div class="post-metadata">

**Author:** ![Zarch](https://community.openenergymonitor.org/user_avatar/community.openenergymonitor.org/zarch/32/7947_2.png) [@Zarch](https://community.openenergymonitor.org/u/Zarch)\
**Post date:** [13 April 2023 13:22 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112/11 "2023-04-13T13:22:11Z")

</div>

Try replcing

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

```

with

```auto
TEMP = 0
CLOUD_COVER = 0

```

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

---

<div class="post-metadata">

**Author:** ![rolfbartels](https://community.openenergymonitor.org/letter_avatar_proxy/v4/letter/r/e0b2c6/32.png) [@rolfbartels](https://community.openenergymonitor.org/u/rolfbartels)\
**Post date:** [17 April 2023 09:23 UTC](https://community.openenergymonitor.org/t/pvoutput-python-script-emoncms-org-pvoutput/10112/12 "2023-04-17T09:23:04Z")

</div>

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

> [@PVOutput from Emon feeds script](https://community.openenergymonitor.org/t/pvoutput-from-emon-feeds-script/21360):
>
> Hi all, [Here’s](https://cloud.workshopdirector.com.au/s/4tXwrKR6S4x8x3T) a script that will take values from your feeds and push them to [PVOutput.org](http://PVOutput.org) Enjoy \<?php #Global Variables // pvoutput API key here; OLD //$Feed\_api\_key = '091119xxxxxxxxxxxxxxxxxxxx4eb3ca'; // pvoutput API key here; $PV\_api\_key = '3c4a95xxxxxxxxxxab8007c'; // PVOutput.orgSystem ID here $SystemID = '12345'; //EMONCms Local IP Here $EMONCms\_Local\_IP = "192.168.15.208"; //EmonCMS Read API Key Here $EmonCMS\_Read\_API\_Key = "091119xxxxxxxxxxxxxxxxb3ca"; //Add CronTab Job once…

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.
