Roland,

Could you please replace the file user/wetter.py with this one, then try
again?

-tk

On Sun, Jun 14, 2020 at 3:11 AM Roland Lang <[email protected]> wrote:

> Hi,
> yesterday I updated my weewx installation from python2 to python3. The
> Upload to wetter.com fails now with following error (but weewx keeps on
> working):
>
> Jun 14 10:25:29 wetter python3[5775]: weewx[5775] ERROR weewx.restx:
> Wetter: Unexpected exception of type <class 'TypeError'>
> Jun 14 10:25:29 wetter python3[5775]: weewx[5775] ERROR weewx.restx: ***
> Traceback (most recent call last):
> Jun 14 10:25:29 wetter python3[5775]: weewx[5775] ERROR weewx.restx: ***
>   File "/usr/share/weewx/weewx/restx.py", line 378, in run_loop
> Jun 14 10:25:29 wetter python3[5775]: weewx[5775] ERROR weewx.restx: ***
>     self.process_record(_record, dbmanager)
> Jun 14 10:25:29 wetter python3[5775]: weewx[5775] ERROR weewx.restx: ***
>   File "/usr/share/weewx/weewx/restx.py", line 442, in process_record
> Jun 14 10:25:29 wetter python3[5775]: weewx[5775] ERROR weewx.restx: ***
>     self.post_with_retries(_request, data)
> Jun 14 10:25:29 wetter python3[5775]: weewx[5775] ERROR weewx.restx: ***
>   File "/usr/share/weewx/weewx/restx.py", line 484, in post_with_retries
> Jun 14 10:25:29 wetter python3[5775]: weewx[5775] ERROR weewx.restx: ***
>     self.check_response(_response)
> Jun 14 10:25:29 wetter python3[5775]: weewx[5775] ERROR weewx.restx: ***
>   File "/usr/share/weewx/user/wetter.py", line 143, in check_response
> Jun 14 10:25:29 wetter python3[5775]: weewx[5775] ERROR weewx.restx: ***
>     if txt.find('"errorcode":"100"') != -1 or \
> Jun 14 10:25:29 wetter python3[5775]: weewx[5775] ERROR weewx.restx: ***
> TypeError: argument should be integer or bytes-like object, not 'str'
> Jun 14 10:25:29 wetter python3[5775]: weewx[5775] CRITICAL weewx.restx:
> Wetter: Thread terminating. Reason: argument should be integer or bytes-like
> object, not 'str'
>
> I got it working again by commenting out the whole if..else statement in
> wetter.py, as it is only a check for errors. But that's of course not the
> final solution :-)
>     140     def check_response(self, response):
>     141         """Override, and check for wetter errors."""
>     142         txt = response.read().lower()
>     143   #     if txt.find('"errorcode":"100"') != -1 or \
>     144   #        txt.find('"errorcode":"101"') != -1 or \
>     145   #        txt.find('"errorcode":"102"') != -1:
>     146   #         raise weewx.restx.BadLogin(txt)
>     147   #     elif txt.find('"status":"error"') != -1:
>     148   #         raise weewx.restx.FailedPost("Server returned '%s'" %
> txt)
>
> Can you please help me? I don't have a clue about python (yet).
>
> Regards,
> Roland
>
> --
> 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/137870dd-4d32-4288-9e27-2fcc0a6b26ado%40googlegroups.com
> <https://groups.google.com/d/msgid/weewx-user/137870dd-4d32-4288-9e27-2fcc0a6b26ado%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
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/CAPq0zEB580Qa2FFN93t-nihNEHjM%2BC7%2B6OsPGDX3GX%2B%3DpdzDWg%40mail.gmail.com.
# Copyright 2013-2020 Matthew Wall
"""
Upload data to wetter.com
  http://wetter.com

[StdRESTful]
    [[Wetter]]
        enable = true | false
        username = STATION ID
        password = STATION PASSWORD
"""

try:
    # Python 3
    import queue
except ImportError:
    import Queue as queue
import re
import sys
import time
try:
    # Python 3
    from urllib.parse import urlencode
except ImportError:
    # Python 2
    from urllib import urlencode

import weewx
import weewx.restx
import weewx.units

VERSION = "0.6"
API_VERSION = "5.0.2 - 2015/06/01"

if weewx.__version__ < "3":
    raise weewx.UnsupportedFeature("weewx 3 is required, found %s" %
                                   weewx.__version__)

try:
    # Test for new-style weewx logging by trying to import weeutil.logger
    import weeutil.logger
    import logging
    log = logging.getLogger(__name__)

    def logdbg(msg):
        log.debug(msg)

    def loginf(msg):
        log.info(msg)

    def logerr(msg):
        log.error(msg)

except ImportError:
    # Old-style weewx logging
    import syslog

    def logmsg(level, msg):
        syslog.syslog(level, 'Wetter: %s' % msg)

    def logdbg(msg):
        logmsg(syslog.LOG_DEBUG, msg)

    def loginf(msg):
        logmsg(syslog.LOG_INFO, msg)

    def logerr(msg):
        logmsg(syslog.LOG_ERR, msg)


class Wetter(weewx.restx.StdRESTful):
    def __init__(self, engine, config_dict):
        """This service recognizes standard restful options plus the following:

        username: username

        password: password
        """
        super(Wetter, self).__init__(engine, config_dict)        
        loginf("service version is %s" % VERSION)
        loginf("wetter API version is %s" % API_VERSION)
        site_dict = weewx.restx.get_site_dict(config_dict, 'Wetter', 'username', 'password')
        if site_dict is None:
            return

        site_dict['manager_dict'] = weewx.manager.get_manager_dict_from_config(
            config_dict, 'wx_binding')

        self.archive_queue = queue.Queue()
        self.archive_thread = WetterThread(self.archive_queue, **site_dict)
        self.archive_thread.start()
        self.bind(weewx.NEW_ARCHIVE_RECORD, self.new_archive_record)
        loginf("Data will be uploaded for station id %s" % site_dict['username'])

    def new_archive_record(self, event):
        self.archive_queue.put(event.record)

class WetterThread(weewx.restx.RESTThread):

    _SERVER_URL = 'http://interface.wetterarchiv.de/weather'
    _DATA_MAP = {'hu':  ('outHumidity', '%.0f'), # percent
                 'te':  ('outTemp',     '%.1f'), # C
                 'dp':  ('dewpoint',    '%.1f'), # C
                 'pr':  ('barometer',   '%.1f'), # hPa
                 'wd':  ('windDir',     '%.0f'), # degrees
                 'ws':  ('windSpeed',   '%.1f'), # m/s
                 'wg':  ('windGust',    '%.1f'), # m/s
                 'pa':  ('hourRain',    '%.2f'), # mm
                 'rr':  ('rainRate',    '%.2f'), # mm/hr
                 'uv':  ('UV',          '%.0f'), # uv index
                 'sr':  ('radiation',   '%.2f'), # W/m^2
                 'hui': ('inHumidity',  '%.0f'), # percent
                 'tei': ('inTemp',      '%.1f'), # C
                 'huo': ('extraHumid1', '%.0f'), # percent
                 'teo': ('extraTemp1',  '%.1f'), # C
                 'tes': ('soilTemp1',   '%.1f')  # C
                 }

    def __init__(self, queue, username, password, manager_dict,
                 server_url=_SERVER_URL, skip_upload=False,
                 post_interval=None, max_backlog=sys.maxsize, stale=None,
                 log_success=True, log_failure=True,
                 timeout=60, max_tries=3, retry_wait=5):
        super(WetterThread, self).__init__(queue,
                                           protocol_name='Wetter',
                                           manager_dict=manager_dict,
                                           post_interval=post_interval,
                                           max_backlog=max_backlog,
                                           stale=stale,
                                           log_success=log_success,
                                           log_failure=log_failure,
                                           max_tries=max_tries,
                                           timeout=timeout,
                                           retry_wait=retry_wait,
                                           skip_upload=skip_upload)
        self.username = username
        self.password = password
        self.server_url = server_url

    def check_response(self, response):
        """Override, and check for wetter errors."""
        txt = response.read().decode().lower()
        if txt.find('"errorcode":"100"') != -1 or \
           txt.find('"errorcode":"101"') != -1 or \
           txt.find('"errorcode":"102"') != -1:
            raise weewx.restx.BadLogin(txt)
        elif txt.find('"status":"error"') != -1:
            raise weewx.restx.FailedPost("Server returned '%s'" % txt)

    def format_url(self, in_record):
        """Override, and format an URL for wetter"""
        # put everything into the right units
        record = weewx.units.to_METRICWX(in_record)

        # put data into expected scaling, structure, and format
        values = {}
        values['id'] = self.username
        values['pwd'] = self.password
        values['sid'] = 'weewx'
        values['ver'] = weewx.__version__
        values['dtutc'] = time.strftime('%Y%m%d%H%M', time.gmtime(record['dateTime']))
        for key in self._DATA_MAP:
            rkey = self._DATA_MAP[key][0]
            if rkey in record and record[rkey] is not None:
                values[key] = self._DATA_MAP[key][1] % record[rkey]

        url = "%s?%s" % (self.server_url, urlencode(values))
        if weewx.debug >= 2:
            logdbg('url: %s' % re.sub(r"passwort=[^\&]*", "passwort=XXX", url))
        return url


# Do direct testing of this extension like this:
#   PYTHONPATH=WEEWX_BINDIR python WEEWX_BINDIR/user/wetter.py
if __name__ == "__main__":
    import optparse

    weewx.debug = 2

    try:
        # WeeWX V4 logging
        weeutil.logger.setup('wetter', {})
    except NameError:
        # WeeWX V3 logging
        syslog.openlog('wetter', syslog.LOG_PID | syslog.LOG_CONS)
        syslog.setlogmask(syslog.LOG_UPTO(syslog.LOG_DEBUG))

    usage = """%prog --user USERNAME --pw PASSWORD [--version] [--help]"""

    parser = optparse.OptionParser(usage=usage)
    parser.add_option('--version', dest='version', action='store_true',
                      help='display driver version')
    parser.add_option('--user', metavar='USERNAME',
                      help='The username')
    parser.add_option('--pw', metavar='PASSWORD', help='Password for USERNAME')
    (options, args) = parser.parse_args()

    if options.version:
        print("wetter uploader version %s" % VERSION)
        exit(0)

    if options.user is None or options.pw is None:
        exit("You must supply both option --user and option --pw.")

    print("Using username '%s' and password '%s'" % (options.user, options.pw))
    q = queue.Queue()
    t = WetterThread(q, options.user, options.pw, manager_dict=None)
    t.start()
    q.put({'dateTime': int(time.time() + 0.5),
           'usUnits': weewx.US,
           'outTemp': 32.5,
           'inTemp': 75.8,
           'outHumidity': 24})
    q.put(None)
    t.join(20)

Reply via email to