Month: September 2018

  • Call a php webpage from a IFTTT applet using Google Assistant

    I wanted to be able to wake up PC on my Lan using voice commands. To achieve that, I did implement a solution using Google Assistant, IFTTT and a php web page hosted on my NAS.

    Click to Read More

    Regarding IFTTT, you must have an account. Then,

    • Create a new applet,
    • Choose the service “Google Assistant”
      • Choose a trigger, ex.: “Say a phrase with a text ingredient”
      • Type a phrase in “What do you want to say?” such as “Wake up my PC $” ($ is the symbol to be used for the “ingredient”)
      • Type a phrase in “What do you want the Assistant to say in response?” such as “Ok, I will wake up $”
    • Choose next an action service “Webhooks” (to “make a web request”)
      • Type the url of your web page: http://<public Ip of your NAS>/<some path>/action.php?do=wakeup&param={{TextField}} ({{TextField}} will take the value of the ingredient)
      • Chose the “method”: GET
      • Chose the “content type”: text/plain

    Regarding the php web page (action.php), I had to do some fine tuning… So, I started with a page logging all information received from IFTTT:

    [php]</pre>
    <?php
    // https://gist.github.com/magnetikonline/650e30e485c0f91f2f40
    class DumpHTTPRequestToFile
    {
    public function execute($targetFile)
    {
    $boby = json_decode(file_get_contents(‘php://input’) , true);

    $data = sprintf("<h2><u>IFTTT call at %s on %s</u></h2><h3>Method:</h3>", date(‘h:i:s’) , date(‘d/m/Y’));
    $data .= sprintf("<blockquote>%s (%s): %s </blockquote><h3>HTTP headers:</h3><ul>", $_SERVER[‘REQUEST_METHOD’], $_SERVER[‘SERVER_PROTOCOL’], htmlentities($_SERVER[‘REQUEST_URI’]));
    foreach ($this->getHeaderList() as $name => $value)
    {
    $data .= "<li><b>" . $name . ‘</b>: ‘ . $value . "</li>";
    }

    $data .= "</ul><h3>Post:</h3><ul>";
    foreach ($_POST as $key => $value) $data .= "<li>" . $key . ‘=’ . $value . ‘</li>’;

    $bodyhtml = $this->jsonToTable($boby);
    $data .= "</ul><h3>Request body:</h3><blockquote>$bodyhtml</blockquote>";

    $action = trim(strtolower($_GET[‘action’]));
    $action = preg_replace(‘/^ *de +/’, ”, $action);
    $action = preg_replace(‘/^ *d *\’ +/’, ”, $action);

    $param = trim(strtolower($_GET[‘param’]));
    $param = preg_replace(‘/^ *de +/’, ”, $param);
    $param = preg_replace(‘/^ *d *\’ +/’, ”, $param);

    $data .= "<h3>Requested Action:</h3><blockquote>$action: $param</blockquote>";

    similar_text(strtolower($param) , "zeus", $percent);
    $data .= "Zeus: $percent %<br>";

    similar_text(strtolower($param) , "chaos", $percent);
    $data .= "Chaos: $percent %<br>";

    file_put_contents($targetFile, $data . file_get_contents($targetFile) . "\n");

    echo (nl2br($data));
    }

    private function getHeaderList()
    {
    $headerList = [];
    foreach ($_SERVER as $name => $value)
    {
    if (preg_match(‘/^HTTP_/’, $name))
    {
    // convert HTTP_HEADER_NAME to Header-Name
    $name = strtr(substr($name, 5) , ‘_’, ‘ ‘);
    $name = ucwords(strtolower($name));
    $name = strtr($name, ‘ ‘, ‘-‘);
    // add to list
    $headerList[$name] = $value;
    }
    }
    return $headerList;
    }

    private function jsonToTable($data)
    {
    $table = "<table class=’json-table’ width=’100%’>";
    foreach ($data as $key => $value)
    {
    $table .= "<tr valign=’top’>";
    if (!is_numeric($key))
    {
    $table .= "
    <td>
    <strong>" . $key . ":</strong>
    </td>
    <td>
    ";
    }
    else
    {
    $table .= "
    <td colspan=’2′>
    ";
    }
    if (is_object($value) || is_array($value))
    {
    $table .= jsonToTable($value);
    }
    else
    {
    $table .= $value;
    }
    $table .= "
    </td>
    </tr>
    ";
    }
    $table .= "</table>";
    return $table;
    }
    }

    (new DumpHTTPRequestToFile)->execute(‘./action.html’);

    ?>
    <pre>[/php]

    The log is stored in a html page “log.html”.

    Notes:

    • I notice that Google was not good at recognizing the name of my PC (IMO because I use French sentences). So I am using a php command “similar_text” to evaluate the “ingredient”. But this is really far from effective.
    • I tried to use a “POST” method instead of “Get” and a Content Type “application/json”, it works. But when I add a Body like {“token”:”mseries”,”command”: “<<<{{TextField}}>>>”, ”test”: “data”}, I don’t see it received by my php page 🙁
    • If Google Assistant does not call correcly IFTTT, look at you voice command history to be sure it understood you order: https://myactivity.google.com/myactivity?restrict=vaa&utm_source=help
    • If Google Assistant understood correctly your command, but IFTTT didn’t call your web page, look at your IFTTT activity: https://ifttt.com/activity

    A log for a call using a GET method will look like:

    IFTTT call at 11:32:29 on 25/09/2018

    Method: GET (HTTP/1.1): /ifttt/action.php?action=wakeup&param=CARROS

    HTTP headers:

    X-Newrelic-Transaction: PxQGUlECCwFRBVEEVQAAAlQTGlUDChAHHEAJVA1cAgMKA1gEVFNVUVUHFU1EAQACBV1UBlUTag==
    X-Newrelic-Id: VwAOU1RRGwAFUFZUAwQE
    Content-Type: text/plain
    Content-Length: 74
    Connection: close
    Host: olympe.letroye.be
    X-Real-Port: 55748
    X-Port: 80
    X-Real-Ip: 54.164.110.125
    X-Forwarded-By: 192.168.0.200

    Post:

    Request body:

    Requested Action: wakeup: CARROS

    Zeus: 20 %
    Chaos: 72.727272727273 %

    A log for a call using a POST method with application/json content-type will look like:

    IFTTT call at 11:41:14 on 25/09/2018

    Method: POST (HTTP/1.1): /ifttt/action.php?action=wakeup&param=Kaos

    HTTP headers:

    X-Newrelic-Id: VwAOU1RRGwAFUFZUAwQE
    Content-Type: application/json
    Content-Length: 77
    Connection: close
    Host: olympe.letroye.be
    X-Real-Port: 59892
    X-Port: 80
    X-Real-Ip: 54.211.16.53
    X-Forwarded-By: 192.168.0.200

    Post:

    Request body:

    Requested Action: wakeup: kaos

    Zeus: 25 %
    Chaos: 66.666666666667 %

    Loading