Discovergy Stromzähler einbinden

Homematic-, TCL- und Shell-Script, Toolchain, C, etc.

Moderator: Co-Administratoren

alchy
Beiträge: 10754
Registriert: 24.02.2011, 01:34
System: CCU
Hat sich bedankt: 65 Mal
Danksagung erhalten: 673 Mal

Re: Discovergy Stromzähler einbinden

Beitrag von alchy » 30.08.2017, 19:19

Aber mein obiges Script funktioniert ja, was willst du denn machen?

Alchy

Blacklist................... almost full
Ignoranz ist die Summe aller Maßnahmen die man ergreift, um bestehende Tatsachen nicht sehen zu müssen.

© Sandra Pulsfort (*1974)

Lies bitte die Logik von WebUI Programmen und die Tipps und Tricks für Anfänger.

Wichtig auch CUxD ersetzt System.exec. Die HM Script Doku (Downloadart Skripte) hilft auch weiter.
Zum Testen von Scripten den >> HomeMatic Script Executor << von Anli benutzen.

Ferry.Icker
Beiträge: 15
Registriert: 21.08.2017, 17:17

Re: Discovergy Stromzähler einbinden

Beitrag von Ferry.Icker » 30.08.2017, 23:47

Hallo Alchy,

ich wollte die Json API von Discovergy benutzen. Mit Authentifizierung usw.
Dein Script basiert noch auf der alten API. Die wird aber nicht weiter unterstützt.

Mfg
Ferry

alchy
Beiträge: 10754
Registriert: 24.02.2011, 01:34
System: CCU
Hat sich bedankt: 65 Mal
Danksagung erhalten: 673 Mal

Re: Discovergy Stromzähler einbinden

Beitrag von alchy » 30.08.2017, 23:52

Ferry.Icker hat geschrieben: Dein Script basiert noch auf der alten API. Die wird aber nicht weiter unterstützt.
Mag sein, aber es reicht ags. noch.

Alchy

Blacklist................... almost full
Ignoranz ist die Summe aller Maßnahmen die man ergreift, um bestehende Tatsachen nicht sehen zu müssen.

© Sandra Pulsfort (*1974)

Lies bitte die Logik von WebUI Programmen und die Tipps und Tricks für Anfänger.

Wichtig auch CUxD ersetzt System.exec. Die HM Script Doku (Downloadart Skripte) hilft auch weiter.
Zum Testen von Scripten den >> HomeMatic Script Executor << von Anli benutzen.

Ferry.Icker
Beiträge: 15
Registriert: 21.08.2017, 17:17

Re: Discovergy Stromzähler einbinden

Beitrag von Ferry.Icker » 31.08.2017, 08:59

Hi Alchy,

ja, im Moment reicht es noch. Ich denke spätestens wenn neue Parameter zum Abfragen via web request hinzukommen, wird man wohl die neue API nutzen müssen.
Ich werde mich dann noch mal melden.

Vielen Dank für deine Mühen und antworten.

MfG
Ferry Icker

Fratra
Beiträge: 2
Registriert: 11.02.2018, 13:30

Re: Discovergy Stromzähler einbinden

Beitrag von Fratra » 11.02.2018, 13:36

Hallo Zusammen,

Ich plane gerade mehrere Discovergy Zähler einzusetzen um ein BHKW zu betreiben. Hat jemand die Zähler im Fhem mit der neuen API bereits in Funktion?

Auch eine Lösung mit HTTPMOD wäre interessant, da ich schon einige andere Werte über das Modul auslese.

Tueftler1983
Beiträge: 2
Registriert: 21.05.2018, 01:26

Re: Discovergy Stromzähler einbinden

Beitrag von Tueftler1983 » 21.05.2018, 01:29

Hallo ist hier schon jemand weiter gekommen mit der neuen API?

Mit der Alten hatte ich den Zähler schön über HTTPMOD in FHEM eingebunden aber mit der neuen Mit Oauth und Tokken komme ich nicht klar

Tueftler1983
Beiträge: 2
Registriert: 21.05.2018, 01:26

Re: Discovergy Stromzähler einbinden

Beitrag von Tueftler1983 » 21.05.2018, 08:55

Ich habe da was bei ip-symcon gefunden vielleicht hilft es ja weiter:

Code: Alles auswählen

<?php
define('__ROOT__', dirname(dirname(__FILE__)));
require_once(__ROOT__ . '/libs/ModuleHelper.class.php');
/**
 * Class GetFresh
 * Driver to GetFresh API (inofficial)
 *
 * @version     0.1
 * @category    Symcon
 * @package     de.codeking.symcon
 * @author      Frank Herrmann <frank@codeking.de>
 * @link        https://codeking.de
 * @link        https://github.com/CodeKing/de.codeking.symcon
 *
 *
 * @ToDo: short interval for current settings
 * @ToDo: get relevant data:
 * @ToDo: current consumption (kWh)
 * @ToDo: current solar (kWh)
 * @ToDo: current grid (kWh)
 * @ToDo: consumption yesterday (kWh)
 * @ToDo: consumption devices (kWh / €)
 */
class GetFresh extends ModuleHelper
{
    protected $prefix = 'GF';
    private $email;
    private $password;
    private $token;
    private $position_offset = 0;
    public $data = [];
    protected $archive_mappings = [ // archive: 0 = default, 1 = counter
        'Base Price' => 0,
        'Price per kWh' => 0,
        'Current Price' => 0,
        'Meter Reading' => 1,
        'Power' => 0
    ];
    protected $profile_mappings = [
        'Base Price' => 'Price',
        'Price per kWh' => 'Price',
        'Meter Reading' => 'kWh',
        'Power' => 'Watt',
        'Power L1' => 'Watt',
        'Power L2' => 'Watt',
        'Power L3' => 'Watt',
        'Provider' => '~String'
    ];
    /**
     * create instance
     */
    public function Create()
    {
        parent::Create();
        // register public properties
        $this->RegisterPropertyString('email', 'user@email.com');
        $this->RegisterPropertyString('password', '');
        $this->RegisterPropertyInteger('interval', 60); // in seconds
        // register timer
        $this->RegisterTimer('UpdateData', 0, $this->prefix . '_Update($_IPS[\'TARGET\']);');
        $this->RegisterTimer('UpdateTariffData', 60 * 1000, $this->prefix . '_UpdateTariff($_IPS[\'TARGET\']);');
    }
    /**
     * execute, when kernel is ready
     */
    protected function onKernelReady()
    {
        // update timer
        $this->SetTimerInterval('UpdateData', $this->ReadPropertyInteger('interval') * 1000);
        // Update tariff details
        $this->UpdateTariff();
        // Update data
        $this->Update();
    }
    /**
     * Read config
     */
    private function ReadConfig()
    {
        // get settings
        $this->email = $this->ReadPropertyString('email');
        $this->password = $this->ReadPropertyString('password');
        $this->token = $this->GetBuffer('token');
        // return if service or internet connection is not available
        if (!Sys_Ping('getfresh.energy', 1000)) {
            $this->_log('GetFresh', 'Error: api or internet connection not available!');
            exit(-1);
        }
        // check if email and password are provided
        if (!$this->email || !$this->password) {
            return false;
        }
        // read access token
        if (!$this->token) {
            $this->token = $this->GetBuffer('token');
        }
        // login if no valid token was provided
        if (!$this->token) {
            $this->Login();
        }
        // simple error handling
        if (!$this->token) {
            $this->SetStatus(201);
            $this->_log('GetFresh', 'Error: The email address or password of your account is invalid!');
            exit(-1);
        }
        // everything looks ok, start
        $this->SetStatus(102);
    }
    /**
     * read & update tariff data
     */
    public function UpdateTariff()
    {
        // read config
        $this->ReadConfig();
        // get tariff provider name
        if ($profile = $this->Api('profile')) {
            $this->data['Provider'] = $profile['brandName'];
        }
        // get tariff
        if ($tariff = $this->Api('consumptionCurrentMonth')) {
            $this->data['Base Price'] = $tariff['monthlyBasePrice']['value'];
            $this->data['Price per kWh'] = $tariff['unitPrice']['value'];
        }
        // log data
        $this->_log('GetFresh Tariff Data', json_encode($this->data));
        // save data
        $this->position_offset = 0;
        $this->SaveData();
    }
    /**
     * read & update consumption data
     */
    public function Update()
    {
        // read config
        $this->ReadConfig();
        // get current readings
        if ($currentReadings = $this->Api('currentReadings')) {
            $cnt = count($currentReadings['readings']) - 1;
            $currentReading = $currentReadings['readings'][$cnt];
            $this->data['Meter Reading'] = $currentReading['energyReading'];
            $this->data['Power'] = $currentReading['power'];
            $this->data['Power L1'] = $currentReading['powerPhase1'];
            $this->data['Power L2'] = $currentReading['powerPhase2'];
            $this->data['Power L3'] = $currentReading['powerPhase3'];
        }
        // log data
        $this->_log('GetFresh Data', json_encode($this->data));
        // save data
        $this->position_offset = 10;
        $this->SaveData();
    }
    /**
     * save data to variables
     */
    private function SaveData()
    {
        // loop data and save to variable
        $position = $this->position_offset;
        foreach ($this->data AS $key => $value) {
            $this->CreateVariableByIdentifier([
                'parent_id' => $this->InstanceID,
                'name' => $key,
                'value' => $value,
                'position' => $position
            ]);
            $position++;
        }
        // reset data
        $this->data = [];
    }
    /**
     * basic api to getfresh (inofficial)
     * @param string $request
     * @return array
     */
    public function Api($request = 'currentReadings')
    {
        // build url
        $url = 'https://www.getfresh.energy/links';
        // default data
        $data = [];
        // curl options
        $curlOptions = [
            CURLOPT_TIMEOUT => 10,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer ' . $this->token,
                'Content-Type: application/json',
                'Connection: keep-alive',
                'Accept-Encoding: gzip',
                'User-Agent: okhttp/3.2.0'
            ]
        ];
        // call api
        $ch = curl_init($url);
        curl_setopt_array($ch, $curlOptions);
        $links = curl_exec($ch);
        // get links
        if ($links = json_decode($links, true)) {
            #var_dump($links);
            #exit;
            $links = [
                'currentReadings' => $links['_links']['currentReadings']['href'],
                'consumption' => $links['_links']['consumption']['href'],
                'profile' => $links['_links']['profile']['href'],
                'consumptionCurrentMonth' => $links['_links']['consumptionCurrentMonth']['href']
            ];
            if (isset($links[$request])) {
                curl_setopt($ch, CURLOPT_URL, $links[$request]);
                $result = curl_exec($ch);
                $data = json_decode($result, true);
            }
        }
        // close curl
        curl_close($ch);
        // return data
        return $data;
    }
    /**
     * Login to getfresh
     */
    public function Login()
    {
        $this->_log('GetFresh', sprintf('Logging in to account of %s...', $this->email));
        // login url
        $url = 'https://www.getfresh.energy/oauth/token';
        // curl options
        $curlOptions = [
            CURLOPT_TIMEOUT => 10,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => http_build_query([
                'grant_type' => 'password',
                'username' => $this->email,
                'password' => $this->password
            ]),
            CURLOPT_HTTPHEADER => [
                'Content-Type: application/x-www-form-urlencoded',
                'Accept-Encoding: gzip',
                'Connection: keep-alive',
                'User-Agent: okhttp/3.2.0'
            ],
            CURLOPT_USERPWD => 'fresh-webclient:'
        ];
        // login
        $ch = curl_init($url);
        curl_setopt_array($ch, $curlOptions);
        $result = curl_exec($ch);
        curl_close($ch);
        // extract token
        $json = json_decode($result, true);
        $this->token = isset($json['access_token']) ? $json['access_token'] : false;
        // save valid token
        if ($this->token) {
            $this->SetStatus(102);
            $this->SetBuffer('token', $this->token);
        } // simple error handling
        else {
            $this->SetStatus(201);
            $this->_log('GetFresh', 'Error: The email address or password of your account is invalid!');
            exit(-1);
        }
        return true;
    }
    /**
     * create custom variable profile
     * @param string $profile_id
     * @param string $name
     */
    protected function CreateCustomVariableProfile(string $profile_id, string $name)
    {
        switch ($name):
            case 'Watt':
                IPS_CreateVariableProfile($profile_id, 2); // float
                IPS_SetVariableProfileDigits($profile_id, 0); // 0 decimals
                IPS_SetVariableProfileText($profile_id, '', ' W'); // Watt
                IPS_SetVariableProfileIcon($profile_id, 'Electricity');
                break;
            case 'kWh':
                IPS_CreateVariableProfile($profile_id, 2); // float
                IPS_SetVariableProfileDigits($profile_id, 2); // 2 decimals
                IPS_SetVariableProfileText($profile_id, '', ' kWh'); // Watt
                IPS_SetVariableProfileIcon($profile_id, 'Electricity');
                break;
            case 'Price':
                IPS_CreateVariableProfile($profile_id, 2); // float
                IPS_SetVariableProfileDigits($profile_id, 4); // 4 decimals
                IPS_SetVariableProfileText($profile_id, '', ' €'); // currency symbol
                IPS_SetVariableProfileIcon($profile_id, 'Euro');
                break;
        endswitch;
    }

Fonzo
Beiträge: 6722
Registriert: 22.05.2012, 08:40
System: CCU
Hat sich bedankt: 25 Mal
Danksagung erhalten: 479 Mal

Re: Discovergy Stromzähler einbinden

Beitrag von Fonzo » 21.05.2018, 09:39

Tueftler1983 hat geschrieben:Hallo ist hier schon jemand weiter gekommen mit der neuen API?

Mit der Alten hatte ich den Zähler schön über HTTPMOD in FHEM eingebunden aber mit der neuen Mit Oauth und Tokken komme ich nicht klar
Das ganze nutzt OAuth, daher müsstest Du schauen ob das mit FHEM geht, der Sinn von OAuth ist es ja einen Client eindeutig zu identifizieren. Da es bei FHEM aber keinen allgemeinen OAuth Endpunkt für alle FHEM gibt, bliebe höchstens die Möglichkeit sich individuell selber als Developer anzulegen und den Bearer direkt ins eigene FHEM zu beziehen. Das ist aber eigentlich nicht Sinn von Oauth sondern die Authentifizierung soll ja über einen zertifizierten Oauth Endpunkt erfolgen (OAuth2). Einfacher geht es auf alle Fälle man nutzt Systeme die OAuth über einen OAuth Endpunkt unterstützten, wie das von Dir zitierte Modul für IP-Symcon. Dann wird IP-Symcon als Software authentifiziert und der Bearer an das einzelne IP-Symcon System durchgereicht.

Ferry.Icker
Beiträge: 15
Registriert: 21.08.2017, 17:17

Re: Discovergy Stromzähler einbinden

Beitrag von Ferry.Icker » 21.05.2018, 17:12

Hallo Teufel,
Ich bin auch auf der Suche nach einer Lösung für die neue API von Discovergy. Ich habe mir gestern mal die ganze Nacht um die Ohren geschlagen und es mit dem Widget probiert. Es hat auch fast perfekt funktioniert. Die Requests dauern etwas länger. Das kann aber daran liegen das mir zwei Parameter bei diesem Get-Request sind mir die beiden Parameter "wait=5000" und "since=1526867979612&_=1526865652779" noch nicht ganz klar. Diese Datumswerte sind größer al in der Homematic üblich.

Hier mal ein Bespiel:

Code: Alles auswählen

var getReq="/usr/local/addons/cuxd/extra/curl -s -k \"https://monitoring.mep-werke.de/json/WidgetJSON.getLast?containerId=XXXXX&tokenId=YYYY&widgetType=FLOW_GRAPHIC_WIDGET&wait=5000&since=1526867979612&_=1526865652779\"";
Im Angehängten Bild wird gezeigt wie man den Request in Chrome ermitteln kann.

MfG
Ferry
Dateianhänge
Discovergy Widget.jpg

Fonzo
Beiträge: 6722
Registriert: 22.05.2012, 08:40
System: CCU
Hat sich bedankt: 25 Mal
Danksagung erhalten: 479 Mal

Re: Discovergy Stromzähler einbinden

Beitrag von Fonzo » 21.05.2018, 22:21

Ferry.Icker hat geschrieben: Hier mal ein Bespiel:

Code: Alles auswählen

var getReq="/usr/local/addons/cuxd/extra/curl -s -k \"https://monitoring.mep-werke.de/json/WidgetJSON.getLast?containerId=XXXXX&tokenId=YYYY&widgetType=FLOW_GRAPHIC_WIDGET&wait=5000&since=1526867979612&_=1526865652779\"";
So wird das voraussichtlich nicht funktionieren, da in der Regel der Bearer Token zeitlich begrenzt ist und dann erneut an den Oauth Endpunkt durchgereicht wird. Du kannst also nicht den Token hard codieren sondern musst diesen zumindest prüfen ob der Token noch gültig ist bzw. immer den aktuellen Bearer übergeben (So funktioniert OAuth2). Es bringt also nichts den Bearer einmalig auszulesen, da sich dieser in der Regel häufig aktualisiert.

Antworten

Zurück zu „Softwareentwicklung für die HomeMatic CCU“