Nutzung des API


#1

Ich möchte meine Stromzähler in meinen Openhab einbinden und versuche mich gerade an dem API.
So wie ich https://api.discovergy.com/docs/ verstehe muss ich mich zuerst autorisieren.
Aber wenn ich https://api.discovergy.com/public/v1/oauth1/consumer_token in meinen Browser eingebe bekomme ich folgende Meldung:

HTTP ERROR 405 Method Not Allowed

URI:/public/v1/oauth1/consumer_token

STATUS:405
MESSAGE:Method Not Allowed
|SERVLET:|org.glassfish.jersey.servlet.ServletContainer-725a4e2d

Mein Browser zeigt mir die TLS 1.2 an… daran sollte es also nicht liege.
Was mach ich falsch?
Vielen Dank fürs Helfen
Grüße
Tobi


#2

Die Fehlermeldung “Method Not Allowed” deutet darauf hin, dass es sich um einen GET Request gehandelt hat und nicht wie bei OAuth1 notwendig ein POST Request.

Im Browser würde ich eher die BasicAuthentication verwenden und nicht OAuth1.

Gruß,
Thorsten


#3

So nun hab ich mir HTTPie heruntergeladen und den OAUTH Plug in installiert.

[http --auth-type=oauth1 --auth=‘client-key:tobi.wanka@XXXor.de:Xxxxxxx’ POST https://api.discovergy.com/public/v1/oauth1/consumer_token]

Ich bekomme die Meldung “401 Unauthorized”
Ich habe das gleiche Nutzername und Password verwendet wie beim Login auf My.Discovergy.

Muss noch etwas freigeschaltet werden?
Grüße
Tobias


#4

Hi Tobi,

die Doku unter https://github.com/httpie/httpie-oauth gibt leider wenig her, ich denke du musst trotz des PlugIns noch viel selbst machen. Zuerst wäre ein POST-Request auf …/consumer_token dran, in dem du den client-name übergibst, um als Antwort darauf einen client-key und ein client-secret zu bekommen. Authentifizierung mit E-Mail Adresse und Passwort kommt erst später.

Aus eigener Erfahrung: Ich habe zuerst lange an OAuth gehangen, bevor es endlich geklappt hat, sehr frustrierend. Sobald ich da durch war, hat es mehr Spaß gemacht. Erst danach habe ich eine Python-Bibliothek für Discovergy gefunden, die die Authentifizierung und auch erste Requests (Meter, Values) sehr vereinfach. Viel mehr kann das Paket derzeit aber nicht.

Vielleicht hilft dir mein Code, um den Ablauf zu verstehen. Wie du siehst musste ich auch noch einiges drum rum bauen, damit es klappt, obwohl ich eine OAUTH-Bibliothek nutze.

1.) Der manuelle Weg (Python)

#!/usr/bin/python3

from rauth import OAuth1Service
from urllib.parse import urlencode
import requests

base_url = 'https://api.discovergy.com/public/v1/'
email = 'mail@example.com'
password = 'secret'
client_name = 'WhateverIwantToCallMyClient'

# Get consumer key and secret (not part of OAuth 1.0)
consumer_token_url = base_url + 'oauth1/consumer_token'
response = requests.post(url=consumer_token_url, data={'client': client_name})
if not response:
    print('Error during consumer_token Request\n'
          + ' HTTP Status Code: ' + str(response.status_code) + '\n'
          + ' HTTP Response:    ' + str(response.content))

consumer_key = response.json()['key']
consumer_secret = response.json()['secret']

print('Consumer Key: ' + consumer_key)
print('Consumer Secret: ' + consumer_secret)

discovergy = OAuth1Service(
    name='discovergy',
    consumer_key=consumer_key,
    consumer_secret=consumer_secret,
    request_token_url=base_url + 'oauth1/request_token',
    access_token_url=base_url + 'oauth1/access_token',
    authorize_url=base_url + 'oauth1/authorize',
    base_url=base_url)

# Get OAuth request token
request_token, request_token_secret = discovergy.get_request_token(method='POST')

print('Request Token: ' + request_token)
print('Request Token Secret: ' + request_token_secret)

# Call authorize URL with email and password to get OAuth verifier
authorize_url = discovergy.get_authorize_url(request_token)
authorize_url += '&' + urlencode({'email': email, 'password': password})
print('Authorize URL: ' + authorize_url)

response = requests.get(url=authorize_url)
if not response:
    print('Error during authorize_url Request\n'
          + ' HTTP Status Code: ' + str(response.status_code) + '\n'
          + ' HTTP Response:    ' + str(response.content))

idx = str(response.content).find('oauth_verifier=')
if idx > -1:
    oauth_verifier = str(response.content)[idx + 15:-1]

print('OAuth Verifier: ' + oauth_verifier)

# Get OAuth access token
session = discovergy.get_auth_session(request_token,
                                      request_token_secret,
                                      method='POST',
                                      data={'oauth_verifier': oauth_verifier})

print('Access Token: ' + session.access_token)
print('Access Token Secret: ' + session.access_token_secret)

r = session.get(base_url + 'meters', header_auth=True)
print(str(r.content))

2.) Mit Hilfe des Python-Pakets "PyDiscovergy"

#!/usr/bin/python3

from pydiscovergy import PyDiscovergy
import datetime
import time
import schedule
import requests

email = 'mail@example.com'
password = 'secret'
clientname = 'WhateverIwantToCallMyClient'

discovergy = PyDiscovergy(clientname)
discovergy.login(email, password)

# Get all meters for account
meters = discovergy.get_meters()

#5

Hallo Max,
vielen Dank für die Scripte. Es sieht so aus, als ob die Scripte funktionieren.
Leider hab ich noch keine Discovergy Stromzähler, der hätte am Mittwoch kommen sollen.

Das “PyDiscovergy” läuft ohne Fehler durch und macht aber auch sonst keine Rückmeldung.

Vielleicht kann mir jemand schreiben, welche Ausgabe aus dem Programm angezeigt wird, wenn ein Stromzähler abgefragt wird.

Grüße
Tobias


#6

Hallo,

seit 2 Tagen hab ich jetzt auch einen Zähler und alles funktioniert wunderbar.
Das Python-Paket “PyDiscovergy” gibt mir auch die Zählerdaten aus.
Soweit kann ich auch noch folgen.
Nun möchte ich, daß das Script mir meine aktuellen Verbrauch ausgibt.
Welche “Get-Befehl” muss ich denn abfragen und welche Daten muss ich in der Abfrage mitgeben?
Hat jemand ein Beispiel?
Ich habe auch schon die Seite https://api.discovergy.com/docs/ studiert. Die Seite werde ich aber erst dann verstehen, wenn ich weiss wie es geht. :slight_smile:


#7

Hallo Tobi,

anbei mein Testmodul für pydiscovergy. Ich musste die Klasse Meter in models.py erweitern, da die meterId nicht korrekt ermittelt wurde. Auf diese Weise kann ich erfolgreich einige get-Kommandos abschicken.

Gruß, Christian

models.py:

class Meter:
    def __init__(self, administrationNumber, currentScalingFactor, firstMeasurementTime, \
    fullSerialNumber, internalMeters, lastMeasurementTime, loadProfileType, location, \
    manufacturerId, measurementType, meterId, scalingFactor, serialNumber, type, \
    voltageScalingFactor, *args, **kwargs):
        """Represents a meter"""
        self.administrationNumber = administrationNumber
        self.currentScalingFactor = currentScalingFactor
        self.firstMeasurementTime = firstMeasurementTime
        self.fullSerialNumber = fullSerialNumber
        self.internalMeters = internalMeters
        self.lastMeasurementTime = lastMeasurementTime
        self.loadProfileType = loadProfileType
        self.location = Location(**location)
        self.manufacturerId = manufacturerId
        self.measurementType = measurementType
        self.meterId = meterId
        self.scalingFactor = scalingFactor
        self.serialNumber = serialNumber
        self.type = type
        self.voltageScalingFactor = voltageScalingFactor

    #def get_meter_id(self):
    #    return self.type + "_" + self.serial_number

class Location:
    def __init__(self, city, street, zip, streetNumber, country, *args, **kwargs):
        """Represents a smart meter location"""
        self.city = city
        self.street = street
        self.zip = zip
        self.street_number = streetNumber
        self.country = country

myDiscov.py:

import jsons
import pprint
from pydiscovergy import PyDiscovergy
# Get credentials from mysettings.py
import mysettings


discovergy_instance = PyDiscovergy('myDiscovergyClient')
result = discovergy_instance.login(mysettings.username, mysettings.password)
if not result:
    print('Error: Could not connect to Discovergy Server!')
    exit()

# Get all meters for account
# jsons lib is used to serialize meter class object to json data
meters = jsons.dump(discovergy_instance.get_meters())

# Print all meter data
pprint.pprint(meters)

# Get id from first meter
meterId = meters[0]['meterId']

# Get field names for first meter
field_names = discovergy_instance.get_fieldnames_for_meter(meterId)
pprint.pprint(field_names)

# Get devices for first meter
devices = discovergy_instance.get_devices_for_meter(meterId)
pprint.pprint(devices)

# Get last reading for first meter
reading = discovergy_instance.get_last_reading(meterId)
pprint.pprint(reading)

#8

Hallo @cnause,

vielen Dank für die wertvolle Infos! :+1: Ich wünsche Ihnen schöne Weihnachtszeit und einen guten Rutsch ins neue Jahr.

Pablo Santiago


#9

Hallo,

ich hänge mich hier mal mit ran.

Ich würde ebenfalls gerne die Zähler direkt abfragen, allerdings nicht über das Internet,
sondern per Direktzugriff über das lokale Intranet - also das heimische Netzwerk.
Ein https-Request auf die Direkt IP des Zählers ( https://192.168.xxx.xxx/ )

Wie ist das realisierbar?

Danke & Gruß,

Volker