I agree with peter's comment.
The Davis solar radiation sensor, or any comparable sensor, is measuring a 
global radiation ( direct + diffuse) and the surface of the sensor is 
parallel to the ground.  A fixed threshold, such as 120 W/m2, can be used 
only with sensors measuring direct radiation and that have their surface 
always pointing to the sun (i.e surface of sensor is always perpendicular 
to the axis sun-sensor).
With a Davis solar sensor, applying a fixed threshold to estimate sunshine 
duration give innacurate values. Why?  A simple example, taken from the 
measurements of my Davis solar sensor, will make you understand:
- On December 20, at 9:30, the sun was shining, and my solar sensor, in 
full sun, measured 105 W / m2.
- On June 11, at 10 am, the sky was cloudy, and my solar probe measured 301 
W / m2.
How to choose a fixed threshold so that the sun of December with 105 W / m2 
is considered as sunny and that a radiation of 301W / m2 under a cloudy sky 
of end of June is not considered as sunny?
A measurement of the global solar radiation on a plane parallel to the 
ground is very dependent on the elevation of the sun. This elevation 
changes according to the time of day and according to the seasons.
So with this type of solar sensors, a valid calculation of the sunshine 
duration  can only be done with methods taking into account the elevation 
of the sun at the time of the measurement, calculated according to the 
latitude, longitude, date and the time of observation.

Here is the weewx extension I am using, that I  modified from 
https://github.com/brewster76/util-archer/blob/master/user/radiationhours.py 
 by applying a formula developed by MeteoFrance to estimate sunshine 
duration from Davis sensors. 
(https://forums.infoclimat.fr/f/topic/17151-calcul-duree-ensoleillement/?do=findComment&comment=1216053).
 
 The idea is to determine at each measurements a  threshold value that is 
calculated depending on the date, time and geographic location (latitude 
and longitude) of the sensor. If the measured solar radiation is higher 
than the calculated threshold, the sunshine duration for this measurement 
will be equal to the archive interval, otherwise it will be 0.

"""
Adds a new observation field to weewx: [sunshine_time]
Installation:
    1. Save this file to your user customisations directory (which is often 
/usr/share/weewx/user)
    2. Enable this service in weewx.conf by adding 
user.sunduration.SunshineDuration to the process_services list.
        [Engine]
            [[Services]]
                # This section specifies the services that should be run. They 
are
                # grouped by type, and the order of services within each group
                # determines the order in which the services will be run.
                prep_services = weewx.engine.StdTimeSynch
                process_services = user.sunduration.SunshineDuration, 
weewx.engine.StdConvert, weewx.engine.StdCalibrate, weewx.engine.StdQC, 
weewx.wxservices.StdWXCalculate
    3. Add [sunshine_time] to the database schema so tables include this new 
observation field.
       In weewx.conf, change the wx_binding schema from schemas.wview.schema to 
user.sunduration.schema_with_sunshine_time
        [DataBindings]
            [[wx_binding]]
                # The database must match one of the sections in [Databases].
                # This is likely to be the only option you would want to change.
                database = archive_sqlite
                # The name of the table within the database
                table_name = archive
                # The manager handles aggregation of data for historical 
summaries
                manager = weewx.wxmanager.WXDaySummaryManager
                # The schema defines the structure of the database.
                # It is *only* used when the database is created.
                #schema = schemas.wview.schema
                schema = user.sunduration.schema_with_sunshine_time
    4. Shutdown Weewx and update your database to bring in the new field.
       wee_database weewx.conf --reconfigure
       Make sure you know what you're doing at this point, you can potentially 
corrupt/lose your archive data.
       The weewx customization guide covers this in a lot more detail.
    5. Tell Weewx about the units for this new type
        Add this to user/extensions.py:
        #
        # Units for sunshine_days calculated field
        #
        import weewx.units
        weewx.units.obs_group_dict['sunshine_time'] = 'group_interval'

    6. Use [sunshine_time] in your graphs and html template tags.
    Lots more detail on this process can be found here:
        http://www.weewx.com/docs/customizing.htm#Adding_a_new_observation_type
"""

import syslog
from math import sin,cos,pi,asin
from datetime import datetime
import time
import weewx
from weewx.wxengine import StdService
import schemas.wview

class SunshineDuration(StdService):
    def __init__(self, engine, config_dict):
        # Pass the initialization information on to my superclass:
        super(SunshineDuration, self).__init__(engine, config_dict)

        # Start intercepting events:
        self.bind(weewx.NEW_ARCHIVE_RECORD, self.newArchiveRecord)

    def newArchiveRecord(self, event):
        """Gets called on a new archive record event."""
        seuil = 0
        tempe = float(event.record.get('outTemp'))
        radiation = event.record.get('radiation')
        event.record['sunshine_time'] = 0.0
        if radiation is not None:
            utcdate = datetime.utcfromtimestamp(event.record.get('dateTime'))
            dayofyear = 
int(time.strftime("%j",time.gmtime(event.record.get('dateTime'))))
            theta = 360 * dayofyear / 365
            equatemps = 0.0172 + 0.4281 * cos((pi / 180) * theta) - 7.3515 * 
sin(
                (pi / 180) * theta) - 3.3495 * cos(2 * (pi / 180) * theta) - 
9.3619 * sin(
                2 * (pi / 180) * theta)

            latitude= float(self.config_dict["Station"]["latitude"])
            longitude = float(self.config_dict["Station"]["longitude"])
            corrtemps = longitude * 4
            declinaison = asin(0.006918 - 0.399912 * cos((pi / 180) * theta) + 
0.070257 * sin(
                (pi / 180) * theta) - 0.006758 * cos(2 * (pi / 180) * theta) + 
0.000908 * sin(
                2 * (pi / 180) * theta)) * (180 / pi)

            minutesjour = utcdate.hour*60 + utcdate.minute
            tempsolaire = (minutesjour + corrtemps + equatemps) / 60
            angle_horaire = (tempsolaire - 12) * 15
            hauteur_soleil = asin(sin((pi / 180) * latitude) * sin((pi / 180) * 
declinaison) + cos(
                (pi / 180) * latitude) * cos((pi / 180) * declinaison) * 
cos((pi / 180) * angle_horaire)) * (180 / pi)
            if hauteur_soleil > 3:
                seuil = (0.73 + 0.06 * cos((pi / 180) * 360 * dayofyear / 365)) 
*1080 * pow((sin(pi / 180) * hauteur_soleil), 1.25) * 0.90
                mesure = (((tempe * 1 - 25) * (-0.0012) * radiation) + 
radiation)
                if mesure > seuil:
                    event.record['sunshine_time'] = event.record['interval']

        syslog.syslog(syslog.LOG_DEBUG, "Calculated sunshine_time = %f, based 
on radiation = %f, and threshold = %f" %
                      (event.record['sunshine_time'], radiation, seuil))


schema_with_sunshine_time = schemas.wview.schema + [('sunshine_time', 'REAL')]





-- 
You received this message because you are subscribed to the Google Groups 
"weewx-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/weewx-user/9f684531-e663-4532-b0fd-8a7257741645%40googlegroups.com.

Reply via email to