APICall

Hi geeks ;o)

  {API}Call is a widget for Garmin devices for calling HTTP URLs. Typical usage is for calling REST API of IOT devices or home automation boxes (Fibaro, eedomus, jeedom, zipa, vera ...) or others things via ifttt.com. It's wanted to be very versatile to be used with lots of applications/situations, like open the gate when get back from a run, close shutters from your couch ... or help a guy who has epilepsy to log partial seizures using IFTTT webhooks (it's not a joke I received a mail to thanks for the widget with this story).

I did it initially for my personnal use, and I'm very happy to share it for everyone. More, it's free, so please be kind and clement ;o).

https://apps.garmin.com/en-EN/apps/ac9a81ab-a52d-41b3-8c14-940a9de37544

To be honest the configuration is not so easy but it's the counterpart of the versatility and of the number of available options.

The page of the app describes the majority of options, but you can find the complete guide here : https://apicall.dumesnil.net/

The first version was released 2 years ago I think the widget is now quite accomplished, but it's there always things to improve, so don't hesitate to suggest me something that is missing.

  • Great software, many thanks for the work you put in it. Was able to control our Shelly garage door automation via the Shelly cloud API.

    I also tried to work with the cloud service of openHAB (myopenhab.org), but unfortunately openHAB needs a POST request with a plain text body, which according to your documentation is not supported by Garmin. But still would like to figure out a way to work with openHAB.

    Has anyone here successfully send commands to openHAB items via APICall?

  • Yes, I confirm, as far as I know and referring to the documentation, you can only send JSON or URL_ENCODED. See URL and table at the end of this post.

    One way (it was what I did before I add the "headers" option needed by my IOT server), is to make a little "proxy" with a custom web server. I used apache2, and a simple php script, to get a very simple request and call curl from this script.

    I try to add code of my simple php script, but impossible, I will try to post in a reply.

    ----

    developer.garmin.com/.../Communications.html

    HttpRequestContentType

    Since:

    API Level 1.0.0

    Name Value Since Description See Also
    REQUEST_CONTENT_TYPE_URL_ENCODED 0

    API Level 1.2.0

    Specifies a content type of application/x-www-form-urlencoded

    REQUEST_CONTENT_TYPE_JSON 1

    API Level 1.2.0

    Specifies a content type of application/json

  • The code of the simple php script:

    Note: I used this script on a local network. Security is really not good ... (passwd localy store, input not really checked : overflow ? ...)

    <?php
    // iotGarmin.php
    // usage:
    // iotGarmin.php?what=[action1
    //     |action2
    //     | ...
    // ]
    //

    /////////////////////////////////////////////////////////////////////////////
    // Const //
    /////////////////////////////////////////////////////////////////////////////
    $myLogin = "xxx";
    $myPasswd = "xxx";
    $myIP = "x.x.x.x";

    /////////////////////////////////////////////////////////////////////////////
    // Vars //
    /////////////////////////////////////////////////////////////////////////////
    $what = "";
    $output = "";
    $URL_PATH = "";
    $URL_BODY = "";

    /////////////////////////////////////////////////////////////////////////////
    // Recuperation des variables passees par l'URL //
    /////////////////////////////////////////////////////////////////////////////
    if ($_GET["what"] != "")
        $what = $_GET["what"];

    if ($what != null && strlen($what) > 0) {
        switch ($what) {
            case "action1":
                $URL_PATH = "api/devices/286/action/pressButton";
                $URL_BODY = "{\"args\":[1]}";
            break;
            case "action2":
                $URL_PATH = "api/devices/286/action/pressButton";
                $URL_BODY = "{\"args\":[2]}";
            break;

            default:
                http_response_code(501);
                //echo "DEBUG : bad parameter : (what=" . $what . ")";
                //echo json_encode(["result" => "Invalid what : ". $what]);
        }

        if ($URL_PATH != "") {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, "http://" . $myIP . "/" . $URL_PATH);
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json','Content-Length: ' . strlen($URL_BODY)));
            curl_setopt($ch, CURLOPT_USERPWD, $myLogin . ":" . $myPasswd);
            curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
            curl_setopt($ch, CURLOPT_POSTFIELDS,$URL_BODY);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            $response = curl_exec($ch);
            $info = curl_getinfo($ch);
            curl_close($ch);

            //Return curl return
            if ($info['http_code'] != 202)
                http_response_code($info['http_code']);
            echo $_GET["what"] . " _ " . $_GET["test"];
        }
    } else {
        http_response_code(406);
        // echo "DEBUG : missing parameter : (what=" . $what . ")";
        // echo json_encode(["result" => "missing what"]);
    }

  • Thanks! In case of openHAB, there is a Webhook HTTP binding, which could be used to setup a URL with GET parameters, and take some action. I would have preferred to use the default REST API, but since that is not possible, I'll play around a bit with that binding.

    But in any case, for my main use case, triggering our car gates, the Shelly cloud API works great. I wrote a short blog article about the different options I looked at, why I choose APICall and how I set it up:

    www.the-ninth.com/.../smart-home-control-from-garmin-devices

  • Great article! May I mention it on my website and/or on the page of the app on Garmin IQ?

  • I've now got openHAB to work with GET requests, via that Webhook Binding and some scripts.

    However, I cannot get it to work with APICall and the Bluetooth connection. When I set media:"WIFI-LTE" it works, but without that, I get an error "KO: -300 Request Timeout". When I test the URL on my mobile phone's browser, it works fine. Also the action I defined for Shelly via their cloud service works, so it seems only access to the local network is affected.

    Here is my code:

    {deviceName:"Bedroom",deviceIcon:62,actionName:"Toggle",actionIcon:65,url:"http://192.168.0.10:8080/webhook/d1097152a4?action=toggle&itemName=Steckdose_OG_SZ_Switch"}

    Any idea of what I could be doing wrong?

  • Yes, http (not secured) is not supported by android or IOS, whereas it's OK directly from the watch. Please read the first "common issue" here : apicall.dumesnil.net/releasenotes_en.html

  • Good morning! I found the issue now, in the app settings Local Network access was disabled. After enabling it works with unsecured http. I think when trying MyHomeControl I read there that iOS supports http and https and only Android supports only https. But maybe that is also limited to certain iOS versions, like you write on your page. Mine is iOS 17.4.1, the latest one.

    In my case https does not work, because of the self-signed certificate. But I might have to remedy that anyway, because I also would like to get this to work on my wife’s Garmin in combination with her Android phone. 

  • Below another blog article, on how to setup openHAB to enable calls from Garmin devices in general and APICall in particular:

    www.the-ninth.com/.../openhab-garmin