Link-Tap Bewässerungssteuerung

Moin,

Habe mir heute einen Link-Tap http://www.link-tap.com gekauft. Macht soweit einen guten Eindruck. Alexa/Google-Home Skill, IFTTT und API. Das Teil hat wahlweise sogar einen Durchflussmesser und kann daher zB erkennen, wenn der Schlauch abgesprungen ist.

API Beschreibung gibts:
https://www.link-tap.com/#!/api-for-developers

Habe mir schon viele dieser Teile angeschaut (Eve) und das Ding scheint endlich mal alles zu können was man braucht und macht dabei eine robusten Eindruck.

Ich werde mir wohl eher ein Skript zusammen-klöppeln, um das Teil aus Symcon zu steuern.
Aber vielleicht hat ja jemand Lust ein Modul dazu zu bauen???

-Stefan

Sehe ich das richtig, man kann direkt am gerät das Ventil nicht öffnen sondern nur via App?
Das finde ich schon an den Eve Dingern blöd.

Loerdy

Hallo Loerdy,

richtig, es geht primär nur über die App. Allerdingsspricht ja nichts dagegen, per Protokoll einen Taster zu integrieren, der dann das Start/Stopp-Signal sendet. Den kann man ja dann sogar dort positionieren, wo man ran kommt.

Beschäftige mich gerade ein wenig damit, da Link-Tap meine alten 24V Ventile ablösen soll. (wegen zusätzlichem Nutzen, wie Wasserbedarfsmessung, etc.)

Ein Modul wäre hier echt fein, muß aber passen, da ich echte PHP-Probleme habe :(.

Gruß

Burkhard

Hallo Stefan,

der Link funktioniert leider nicht, erlaube mir daher, hier den funktionierenden zu setzen: Link-Tap http://www.link-tap.com.

Hoffe, dass ist okay.

Gruß

Burkhard

Den Link habe ich im Orginalpost korrigiert. Komisch war eigentlich copy/paste…

Der Support von LinkTap ist ziemlich hilfreich. Hatte ein Problem Familienmitglieder einzuladen. Hat sich herausgestellt, dass Gateway brauchte noch ein Update.

Ich habe angeboten die gröbsten Bugs in der Deutschen Übersetzung der APP zu fixen. Wurde dankbar angenommen (ohne zu Fragen, wurde Bezahlung angeboten). Damit könnten wir einen Fuß in der Tür zu den Entwicklern haben :slight_smile:

Die APP an sich ist etwas chaotisch, aber ansonsten war die Inbetriebnahme völlig Problemlos.

Wenn ihr Fragen zu dem Teil habt, kann ich gerne unterstützen :slight_smile:

Ich hab da prompt mal eine Frage:

Habe mir gestern mal detailliert die API angesehen. Wenn ich dass richtig verstehe, benötigt er immer eine funktionierende Verbindung zur Link-Tap Cloud. Sehe ich dass richtig?

Wenn dem so ist, bedeutet dies, wenn die Cloud nicht erreichbar ist, oder das Internet mal nicht vorhanden ist, geht dann auch die Bewässerung nicht mehr?

Das wiederum fände ich suboptimal.

Gruß

Burkhard

Teils, teils.
Die aktivierten Programme laufen ohne die Cloud weiter. Der zuletzt aktivierte Zeitplan wird immer lokal gespeichert.

Ich will aber auch nicht verhehlen das dieses Teil sicher eines dieser IOT Geräte ist, was man entsorgen kann, wenn die Cloud und App abgeschaltet wird. Wie leider so vieles heutzutage…

…so, habe mir auch so ein Teil gegönnt, funktioniert nicht schlecht (vorher Eve, habe ich wieder zurückgeschickt).

Hat jemand einen kurzen Tipp/Einzeiler, wie ich die API ansteuern kann? Laut Hersteller geht das ja über POST https://www.link-tap.com/api/activateInstantMode, aber leider habe ich hier keine Ahnung… mit Curl…?

Danke und viele Grüße,

Carsten

Mit einem Einzeiler wird das nix ;-).


<?php

$link_tap = new LinkTap('my_username', 'my_apikey', 'my_gateway_id', 'my_taplinker_id');
$link_tap->Watering_On(20);

class LinkTap
{
    private const LINK_TAP_BASE_URL = 'https://www.link-tap.com/api/';
    private const ACTIVATE_INSTANT_MODE = 'activateInstantMode';
    private const ACTIVATE_INTERVAL_MODE = 'activateIntervalMode';

    public $username; // String type. Your LinkTap account's username
    public $apiKey; // String type. Your API key
    public $gatewayId; // String type. Your LinkTap Gateway's first 16-digits/letters ID, case insensitive, no dash symbol, e,g, 3F7A23FE004B1200
    public $taplinkerId; // String type. Your LinkTap Taplinker's first 16-digits/letters ID, case insensitive, no dash symbol, e,g, 67ABCDEF004B1200

    function __construct(string $username, string $api_key, string $gatewayId, string $taplinkerId)
    {
        $this->username = $username;
        $this->apiKey = $api_key;
        $this->gatewayId = $gatewayId;
        $this->taplinkerId = $taplinkerId;
    }

    /** Watering On
     * @param int $duration The watering duration (unit is minute) the range is from 1 minute to 1439 minutes.
     * @return string
     */
    public function Watering_On(int $duration)
    {
        $url = self::LINK_TAP_BASE_URL . self::ACTIVATE_INSTANT_MODE;
        $data = json_encode([
            'username' => $this->username,
            'apiKey' => $this->apiKey,
            'gatewayId' => $this->gatewayId,
            'taplinkerId' => $this->taplinkerId,
            'action' => true,
            'duration' => $duration,
            'eco' => true,
            'ecoOn' => 1,
            'ecoOff' => 2
        ]);
        $response = $this->PostData($url, $data);
        return $response;
    }

    /** Watering Off
     * @param int $duration
     * @return string
     */
    public function Watering_Off()
    {
        $url = self::LINK_TAP_BASE_URL . self::ACTIVATE_INSTANT_MODE;
        $data = json_encode([
            'username' => $this->username,
            'apiKey' => $this->apiKey,
            'gatewayId' => $this->gatewayId,
            'taplinkerId' => $this->taplinkerId,
            'action' => false,
            'duration' => 0
        ]);
        $response = $this->PostData($url, $data);
        return $response;
    }

    protected function PostData($url, $data)
    {
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_URL, $url);

        $result = curl_exec($ch);
        if (curl_errno($ch)) {
            trigger_error('Error:' . curl_error($ch));
        }
        $info = curl_getinfo($ch);
        // var_dump($info);
        $header_out = curl_getinfo($ch, CURLINFO_HEADER_OUT);
        // var_dump($header_out);
        curl_close($ch);
        return $result;
    }
}


Lesen, versuchen zu verstehen und dann erweitern um die restlichen Befehle. Viel Spass beim bewässern ausprobieren.

…Klasse, danke. Probiere ich morgen gleich mal aus!
Viele Grüße, Carsten

Und konntest Du schon testen ob es funktioniert?

Update wegen ID-Länge!!!

…also nochmals danke, Fonzo! Bin beeindruckt - das Skript hat sofort funktioniert! :):loveips:

Zwei Dinge noch als kurzer Hinweis für alle Nutzer:

  • Die IDs vom Gateway und den TapLinkern darf man nicht mit den in der App angezeigten Bindestrichen in die u.g. Variablen eintragen, da sonst Fehlermeldung
  • App/Webportal zeigen die IDs anonymisiert an (letzten 4 Stellen mit xxxx); Achtung: Die IDs sind auch auf den Geräten mit 20 Digits angegeben, aber die API verträgt nur die ersten 16 Digits! Also nur die ersten 16 Stellen (ohne Bindestrich) im Script eintragen. Die API-Funktion getWateringStatus reagiert in der V1.1 dummerweise bei einer zu langen ID mit dem falschen Status…

Hier noch eine um einige weitere Funktionen ergänzte Version, die restlichen Funktionen baue ich bei Bedarf ein.

$gatewayID = 'xxx'; // ohne Bindestriche, 16 Digits
$taplinker1 = 'xxx'; // ohne Bindestriche, 16 Digits

$link_tap = new LinkTap('xxx', 'xxx', $gatewayID, $taplinker1); 
// $result = $link_tap->Watering_On(20);
// echo $result.PHP_EOL;
// var_dump($result);
$result = $link_tap->Get_All_Devices();
$status = json_decode($result);
print_r($status);

class LinkTap 
{ 
    private const LINK_TAP_BASE_URL = 'https://www.link-tap.com/api/'; 
    private const ACTIVATE_INSTANT_MODE = 'activateInstantMode'; 
    private const ACTIVATE_INTERVAL_MODE = 'activateIntervalMode'; 
    private const QUERY_WATERING_STATUS = 'getWateringStatus';
    private const GET_ALL_DEVICES = 'getAllDevices';

    public $username; // String type. Your LinkTap account's username 
    public $apiKey; // String type. Your API key 
    public $gatewayId; // String type. Your LinkTap Gateway's first 16-digits/letters ID, case insensitive, no dash symbol, e,g, 3F7A23FE004B1200 
    public $taplinkerId; // String type. Your LinkTap Taplinker's first 16-digits/letters ID, case insensitive, no dash symbol, e,g, 67ABCDEF004B1200 

    function __construct(string $username, string $api_key, string $gatewayId, string $taplinkerId) 
    { 
        $this->username = $username; 
        $this->apiKey = $api_key; 
        $this->gatewayId = $gatewayId; 
        $this->taplinkerId = $taplinkerId; 
    } 

    /** Watering On 
     * @param int $duration The watering duration (unit is minute) the range is from 1 minute to 1439 minutes. 
     * @return string 
     */ 
    public function Watering_On(int $duration) 
    { 
        $url = self::LINK_TAP_BASE_URL . self::ACTIVATE_INSTANT_MODE; 
        $data = json_encode([ 
            'username' => $this->username, 
            'apiKey' => $this->apiKey, 
            'gatewayId' => $this->gatewayId, 
            'taplinkerId' => $this->taplinkerId, 
            'action' => true, 
            'duration' => $duration, 
            'eco' => true, 
            'ecoOn' => 1, 
            'ecoOff' => 2 
        ]); 
        $response = $this->PostData($url, $data); 
        return $response; 
    } 

    /** Watering Off 
     * @param int $duration 
     * @return string 
     */ 
    public function Watering_Off() 
    { 
        $url = self::LINK_TAP_BASE_URL . self::ACTIVATE_INSTANT_MODE; 
        $data = json_encode([ 
            'username' => $this->username, 
            'apiKey' => $this->apiKey, 
            'gatewayId' => $this->gatewayId, 
            'taplinkerId' => $this->taplinkerId, 
            'action' => false, 
            'duration' => 0 
        ]); 
        $response = $this->PostData($url, $data); 
        return $response; 
    } 

    /** Watering Status of a single Taplinker
     * @param (string $taplinkerId)
     * @return string 
     */ 
    public function Watering_Status() 
    { 
        $url = self::LINK_TAP_BASE_URL . self::QUERY_WATERING_STATUS; 
        $data = json_encode([ 
            'username' => $this->username, 
            'apiKey' => $this->apiKey,
            'taplinkerId' => $this->taplinkerId 
        ]); 
        $response = $this->PostData($url, $data); 
        return $response; 
    } 

    /** Get All Devices 
     * @param  (string $gatewayId)
     * @return string 
     */ 
    public function Get_All_Devices() 
    { 
        $url = self::LINK_TAP_BASE_URL . self::GET_ALL_DEVICES; 
        $data = json_encode([ 
            'username' => $this->username, 
            'apiKey' => $this->apiKey, 
            'gatewayId' => $this->gatewayId, 
        ]); 
        $response = $this->PostData($url, $data); 
        return $response; 
    } 


    protected function PostData($url, $data) 
    { 
        $ch = curl_init(); 

        curl_setopt($ch, CURLOPT_POST, 1); 
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); 
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); 
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
        curl_setopt($ch, CURLOPT_HEADER, false); // geändert von true damit json_decode() von result funkioniert; falls Header von Interesse, dann curl_getinfo($ch, CURLINFO_HTTP_CODE)
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 
        curl_setopt($ch, CURLOPT_URL, $url); 

        $result = curl_exec($ch); 
        if (curl_errno($ch)) { 
            trigger_error('Error:' . curl_error($ch)); 
        } 
        $info = curl_getinfo($ch); 
        // var_dump($info); 
        $header_out = curl_getinfo($ch, CURLINFO_HEADER_OUT); 
        // var_dump($header_out); 
        curl_close($ch); 
        return $result; 
    } 
}

hallo in die Runde :slight_smile:

glaubt Ihr, dass man das Gerät irgendwie auch ohne die Cloud steuern kann?!

Im Grunde genommen spricht es Zigbee, also wäre es wünschenswert, wenn man es etwa über Zigbee2mqtt ansprechen könnte und auf diese Weise z.B. in NodeRed anbindet.

Habt Ihr evtl eine Idee, wie so etwas realisierbar wäre?

Bis jetzt habe ich mein smarthome cloudfrei gehalten und bin damit sehr zufrieden :slight_smile:

LG
pali

Das Gerät lässt sich ohne Cloud steuern es werden ja lediglich Befehle an eine API gesendet, eine Ansteuerung erfolgt von IP-Symcon zum API Endpunkt von LinkTap. Einfach im Modul Store nach LinkTap suchen, das Modul installieren und Instanzen anlegen und Du hast die Werte des LinkTap bzw. kannst dies steuern.

Oder suchst Du eine Ansteuerung ohne die API, bzw. was verstehst Du in dem Fall unter Cloud?

Im Prinzip habe ich nur der LinkTap G1 heißt es wohl, ohne ein Gateway. Wenn ich es richtig verstanden habe, verbindet sich das Gateway mit dem G1 mittels des ZigBee Protokolls. So hoffe ich, dass man etwa mit einem CP2531 oder conbee Stick mit mit dem G1 kommunizieren kann.
So ähnlich funktioniert es ja auch bei vielen anderen Geräten (Lampen, Steckdosen, etc.), ohne Gateway und ohne irgendwelche Cloud in CN oder sonst wo :slight_smile:

Ach so, ja normalerweise ist der Aufbau denke ich ein Gateway und ein oder mehrere TapLinker.

Keine Ahnung ich weis nicht wie das Gerät kommuniziert. Aber im Prinzip glaube ich nicht, dass sich der ganze Aufwand lohnt, das Gateway selber bekommt man ja meist im Set dazu und auch einzeln kostet das nicht die Welt, ist zumindest nicht viel teurer als ein Conbee Stick und Du hast kein basteln bzw. musst erst mal herausfinden und ewig Zeit investieren wie man mit Zigbee das Gerät auslesen bzw. steuern soll.
Wie so oft funktioniert die Kommunikation dann halt IP-Symcon -> API -> Hersteller Server -> Gateway. Ist halt blöd wenn mal das Internet ausfällt oder der Hersteller Server, aber wahrscheinlich immer noch einfach als versuchen herraus zu bekommen, wie man mit dem LinkTap direkt kommunizieren soll.

danke Fonzo für die Antworten! :slight_smile:

nun, an sich hast Du ja recht :slight_smile:

an dem Setup gefällt mir nicht so ganz, dass ich von einem Dritten abhängig bin. Das würde ich gerne vermeiden.
Die Daten sollen schon „zu Hause“ bleiben :wink:

Gibt halt immer mehr Hersteller, die haben sogar schon Cloud im Namen wie Cloudrain aber auch Gardena läuft über Cloud. Hydrawise kann man denke ich auch lokal auslesen. Ansonsten geht natürlich auch ein Magnetventil und einen Funkaktor das ist dann nur lokal, aber halt kein fertiges Gerät. So was wie ein LinkTap oder auch andere fertige Geräte ist an sich schon nett und spart das basteln und mühsehliges konfigurieren, man hat aber halt immer den schwarzen Peter, dass ohne den Hersteller Server dann nichts mehr geht. Man kann also immer nur hoffen, dass es den Hersteller bzw. den Hersteller Server und das System eine Weile gibt, sonst hat man von einem Tag auf den anderen ein nutzloses Gerät ohne den funktionierenden Hersteller Server.

Hallo Fonzo,

Du bist ein Held!!!
Danke für das Modul!

Habe dein Modul probiert und folgendes ist mir dabei aufgefallen:

  • Die Anleitung ist etwas seltsam, so springst plötzlich zu einem Device Names „Ondillo“ das wie eine Poolsteuerung aussieht
  • Das Anlegen war etwas harkelig hat jetzt aber doch funktioniert. Lag vieleicht an der fehlenden Anleitung…

Gruss,
Stefan

Oh da muss ich wohl noch was ausbessern.

Kannst ja aus Deinen leidvollen Erfahrungen ;-), einen kurze Zusammenfassung schreiben bzw. die Anleitung so weit verbessern das es dann auch verständlich ist, ich übernehme das dann gerne per copy & paste.