Ankündigung

Einklappen
Keine Ankündigung bisher.

Umfrage: Amazon Echo

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • patrickgoll
    antwortet
    Zitat von hotzen Beitrag anzeigen
    das hier meine ich in der aws_lambda.js:
    Code:
    var data = 'json=' + JSON.stringify(event)
    wie du siehst baller ich die payload in den parameter json, das wird wohl so von cherrpy erwartet.

    und ich bin jetzt uebrigens stuck ohne echo oder dot, da alexa.amazon.de sich weigert mich den skill einrichten zu lassen, weil meine spracheinstellungen auf deutsch geändert werden müssten. ich hab nur keine moeglichkeit das zu aendern. lt amazon support braucht man dafuer einen echo oder echo dot und ich hab noch keinen
    Ja das kann ich bestätigen. Ich habe einen Dot und kann das einrichten. Ich habe die OAuth erfolgreich verbunden und wenn ich auf discover Devices klicke kommen eben die oben erwähnten Fehler.

    Also irgendwas wuppt noch nicht so ganz

    Einen Kommentar schreiben:


  • hotzen
    antwortet
    ja, ist eingecheckt als aktuellste version: https://github.com/hotzen/smarthome/.../aws_lambda.js
    s. environmental variables fuer die ganze konfiguration

    Einen Kommentar schreiben:


  • patrickgoll
    antwortet
    Okay das ist ein ziemlich cooler weg das zu machen. Poste mal bitte deine Lambda Funktion ohne Options natürlich Dann kann ich die mit meiner vergleichen. Oder ist das im alexa branch die aktuellste Version?

    Einen Kommentar schreiben:


  • hotzen
    antwortet
    das hier meine ich in der aws_lambda.js:
    Code:
    var data = 'json=' + JSON.stringify(event)
    wie du siehst baller ich die payload in den parameter json, das wird wohl so von cherrpy erwartet.

    und ich bin jetzt uebrigens stuck ohne echo oder dot, da alexa.amazon.de sich weigert mich den skill einrichten zu lassen, weil meine spracheinstellungen auf deutsch geändert werden müssten. ich hab nur keine moeglichkeit das zu aendern. lt amazon support braucht man dafuer einen echo oder echo dot und ich hab noch keinen

    Einen Kommentar schreiben:


  • hotzen
    antwortet
    kannst es dir erstmal einfacher machen, mein repo in ein extra verzeichnis clonen
    Code:
    git clone https://github.com/hotzen/smarthome.git /opt/smarthome-alexa
    in das verzeichnis rein, dann in den alexa branch wechseln
    Code:
    git checkout alexa
    dann in dein smarthome-plugins einen softlink auf mein alexa-plugin
    Code:
    ln -s /opt/smarthome-alexa/plugins/alexa /usr/local/smarthome/plugins/alexa
    das müsste dann relativ locker funktionieren und sobald meins halbwegs tut, mach ich einen pull request ins smarthomeNG in den develop-branch

    Einen Kommentar schreiben:


  • patrickgoll
    antwortet
    Okay ich glaube das ist jetzt die richtige Gelegenheit für diese Frage. Wenn ich also in meinem /usr/local/smarthome bin. Wie kann ich aus deinem branch "alexa" den ./plugin/alexa rauspullen? Ich checke git einfach so gar nicht muss ich mal offen gestehen.

    Zudem was meintest du soll ich an der payload ändern? Kann dir nicht ganz folgen.

    Danke vorab.

    Einen Kommentar schreiben:


  • hotzen
    antwortet
    ja, das ist dieser bescheidene cherrypy automatismus. schau mal in meine aws_lambda.js, da poste ich die payload an den parameter json. der wird leider von cherrypy so erwartet.

    ansonsten mach mal ein pull, da waren noch ein dutzend bugs drin

    Einen Kommentar schreiben:


  • patrickgoll
    antwortet
    hotzen Ich hab das nun mal versucht und bekomme es aber nicht so recht hin.

    Code:
    root@smartvisu:/usr/local/smarthome/etc# netstat -tulpen
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State       User       Inode       PID/Program name
    tcp        0      0 0.0.0.0:2424            0.0.0.0:*               LISTEN      1000       3209817     11848/python3
    tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      0          11471       818/exim4
    tcp        0      0 0.0.0.0:445             0.0.0.0:*               LISTEN      0          2471412     21699/smbd
    tcp        0      0 0.0.0.0:9000            0.0.0.0:*               LISTEN      1000       3209811     11848/python3
    tcp        0      0 0.0.0.0:139             0.0.0.0:*               LISTEN      0          2471413     21699/smbd
    tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      0          9454        349/rpcbind
    tcp        0      0 0.0.0.0:2323            0.0.0.0:*               LISTEN      1000       3209818     11848/python3
    tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      0          10496       374/sshd
    tcp        0      0 0.0.0.0:35383           0.0.0.0:*               LISTEN      106        9564        358/rpc.statd
    tcp6       0      0 ::1:25                  :::*                    LISTEN      0          11472       818/exim4
    tcp6       0      0 :::55418                :::*                    LISTEN      106        9570        358/rpc.statd
    tcp6       0      0 :::443                  :::*                    LISTEN      0          3153652     10676/apache2
    tcp6       0      0 :::445                  :::*                    LISTEN      0          2471410     21699/smbd
    tcp6       0      0 :::6720                 :::*                    LISTEN      0          9974        1/systemd
    tcp6       0      0 :::139                  :::*                    LISTEN      0          2471411     21699/smbd
    tcp6       0      0 :::111                  :::*                    LISTEN      0          9457        349/rpcbind
    tcp6       0      0 :::80                   :::*                    LISTEN      0          3153648     10676/apache2
    tcp6       0      0 :::22                   :::*                    LISTEN      0          10508       374/sshd
    udp        0      0 0.0.0.0:948             0.0.0.0:*                           0          9453        349/rpcbind
    udp        0      0 127.0.0.1:958           0.0.0.0:*                           0          9556        358/rpc.statd
    udp        0      0 192.168.1.10:3672       0.0.0.0:*                           108        10663       394/knxd
    udp        0      0 0.0.0.0:36862           0.0.0.0:*                           106        9561        358/rpc.statd
    udp        0      0 0.0.0.0:111             0.0.0.0:*                           0          9450        349/rpcbind
    udp        0      0 192.168.1.255:137       0.0.0.0:*                           0          2471215     21658/nmbd
    udp        0      0 192.168.1.10:137        0.0.0.0:*                           0          2471214     21658/nmbd
    udp        0      0 0.0.0.0:137             0.0.0.0:*                           0          2471211     21658/nmbd
    udp        0      0 192.168.1.255:138       0.0.0.0:*                           0          2471217     21658/nmbd
    udp        0      0 192.168.1.10:138        0.0.0.0:*                           0          2471216     21658/nmbd
    udp        0      0 0.0.0.0:138             0.0.0.0:*                           0          2471212     21658/nmbd
    udp6       0      0 :::39685                :::*                                106        9567        358/rpc.statd
    udp6       0      0 :::948                  :::*                                0          9456        349/rpcbind
    udp6       0      0 :::111                  :::*                                0          9455        349/rpcbind

    Code:
    [EG]
       [[Wohnzimmer]]
                    [[[SpotsOfen]]]
                [[[[Schalten]]]]
                type = bool
                enforce_updates = yes
                visu_acl = rw
                nw = yes
                knx_dpt = 1
                knx_listen = 1/0/3
                knx_send = 1/0/0
                knx_cache 1/0/3
            alexa_name = "Wohnzimmer Ofen"
            alexa_actions = turnOn turnOff
                [[[[Dimmen]]]]
                type = num
                            nw = yes
                enforce_updates = yes
                knx_dpt = 5
                knx_listen = 1/0/4
                knx_send = 1/0/2
                knx_cache 1/0/4
            alexa_name = "Wihnzimmer Ofen"
            alexa_actions = setPercentage incrementPercentage decrementPercentage
    Code:
    2016-11-29  10:59:40 INFO     CP Server CP Server Thread-14 192.168.1.1 - - [29/Nov/2016:10:59:40] "GET / HTTP/1.1" 500 1741 "" ""
    2016-11-29  10:59:40 ERROR    CP Server CP Server Thread-15 [29/Nov/2016:10:59:40] HTTP
    Traceback (most recent call last):
      File "/usr/local/lib/python3.4/dist-packages/cherrypy/_cprequest.py", line 670, in respond
        response.body = self.handler()
      File "/usr/local/lib/python3.4/dist-packages/cherrypy/lib/encoding.py", line 220, in __call__
        self.body = self.oldhandler(*args, **kwargs)
      File "/usr/local/lib/python3.4/dist-packages/cherrypy/lib/jsontools.py", line 61, in json_handler
        value = cherrypy.serving.request._json_inner_handler(*args, **kwargs)
      File "/usr/local/lib/python3.4/dist-packages/cherrypy/_cpdispatch.py", line 60, in __call__
        return self.callable(*self.args, **self.kwargs)
      File "/usr/local/smarthome/plugins/alexa/service.py", line 32, in index
        req = cherrypy.request.json
      File "/usr/local/lib/python3.4/dist-packages/cherrypy/__init__.py", line 232, in __getattr__
        return getattr(child, name)
    AttributeError: 'Request' object has no attribute 'json'
    2016-11-29  10:59:40 INFO     CP Server CP Server Thread-15 [29/Nov/2016:10:59:40] HTTP
    Request Headers:
      Content-Type: application/json
      Remote-Addr: 192.168.1.1
      HOST: 192.168.1.10:9000
      CONNECTION: Keep-Alive
      X-FORWARDED-FOR: 52.19.74.195
      X-FORWARDED-HOST: virtual.heneronline.de
      X-FORWARDED-SERVER: virtual.heneronline.de
      Content-Length: 785
      X-FORWARDED-PROTO: https
      AUTHORIZATION: Basic YWxleGE6IU51ckZ1ZXJBbGV4YTIwMTYj
    2016-11-29  10:59:40 INFO     CP Server CP Server Thread-15 192.168.1.1 - - [29/Nov/2016:10:59:40] "GET / HTTP/1.1" 500 1741 "" ""
    2016-11-29  10:59:40 ERROR    CP Server CP Server Thread-16 [29/Nov/2016:10:59:40] HTTP
    Traceback (most recent call last):
      File "/usr/local/lib/python3.4/dist-packages/cherrypy/_cprequest.py", line 670, in respond
        response.body = self.handler()
      File "/usr/local/lib/python3.4/dist-packages/cherrypy/lib/encoding.py", line 220, in __call__
        self.body = self.oldhandler(*args, **kwargs)
      File "/usr/local/lib/python3.4/dist-packages/cherrypy/lib/jsontools.py", line 61, in json_handler
        value = cherrypy.serving.request._json_inner_handler(*args, **kwargs)
      File "/usr/local/lib/python3.4/dist-packages/cherrypy/_cpdispatch.py", line 60, in __call__
        return self.callable(*self.args, **self.kwargs)
      File "/usr/local/smarthome/plugins/alexa/service.py", line 32, in index
        req = cherrypy.request.json
      File "/usr/local/lib/python3.4/dist-packages/cherrypy/__init__.py", line 232, in __getattr__
        return getattr(child, name)
    AttributeError: 'Request' object has no attribute 'json'
    2016-11-29  10:59:40 INFO     CP Server CP Server Thread-16 [29/Nov/2016:10:59:40] HTTP
    Request Headers:
      Content-Type: application/json
      Remote-Addr: 192.168.1.1
      HOST: 192.168.1.10:9000
      CONNECTION: Keep-Alive
      X-FORWARDED-FOR: 52.19.74.195
      X-FORWARDED-HOST: virtual.heneronline.de
      X-FORWARDED-SERVER: virtual.heneronline.de
      Content-Length: 785
      X-FORWARDED-PROTO: https
      AUTHORIZATION: Basic YWxleGE6IU51ckZ1ZXJBbGV4YTIwMTYj
    2016-11-29  10:59:40 INFO     CP Server CP Server Thread-16 192.168.1.1 - - [29/Nov/2016:10:59:40] "GET / HTTP/1.1" 500 1741 "" ""
    Code:
     
     START RequestId: 033c7ec2-b61a-11e6-bc33-bd93f7e53f34 Version: $LATEST 2016-11-29T09:55:53.031Z	033c7ec2-b61a-11e6-bc33-bd93f7e53f34	request: 500 / {"date":"Tue, 29 Nov 2016 09:55:52 GMT","server":"Apache","content-length":"1741","content-type":"text/html;charset=utf-8","vary":"Accept-Encoding","cache-control":"no-cache","connection":"close"} 2016-11-29T09:55:53.032Z	033c7ec2-b61a-11e6-bc33-bd93f7e53f34	{"errorMessage":"DependentServiceUnavailableError"} END RequestId: 033c7ec2-b61a-11e6-bc33-bd93f7e53f34 REPORT RequestId: 033c7ec2-b61a-11e6-bc33-bd93f7e53f34	Duration: 868.87 ms	Billed Duration: 900 ms 	Memory Size: 128 MB	Max Memory Used: 10 MB
    Ne Idee?

    Einen Kommentar schreiben:


  • patrickgoll
    antwortet
    Danke hotzen für das Teilen deines Codes. Ich schau mir das mal an. Nach dem ersten Überfliegen würde ich sagen hast du genau das programmiert, was ich gerne gemacht hätte. Dafür war ich wohl nicht klug genug ^^

    Einen Kommentar schreiben:


  • pfischi
    antwortet
    Zitat von hotzen Beitrag anzeigen
    hab nen plugin geschrieben, kannst ja parallel schauen ob du es zum laufen bekommst.
    das setup mit dem amazon skill und skill-enabling in der app ist ja wahnsinnig kompliziert...

    https://github.com/hotzen/smarthome/.../plugins/alexa
    Danke für deinen Code.

    Gruss,

    Stefan

    Einen Kommentar schreiben:


  • hotzen
    antwortet
    hab nen plugin geschrieben, kannst ja parallel schauen ob du es zum laufen bekommst.
    das setup mit dem amazon skill und skill-enabling in der app ist ja wahnsinnig kompliziert...

    https://github.com/hotzen/smarthome/.../plugins/alexa

    Einen Kommentar schreiben:


  • patrickgoll
    antwortet
    Noch sind wir nicht am Ende angekommen. Ich bin von einem release fähigen Stand noch weit entfernt. Wenn auch dieser Durchbruch schonmal der Grundstein für das ganze Vorhaben ist. Ich glaube wir können hier was sehr gutes erreichen.

    Einen Kommentar schreiben:


  • henfri
    antwortet
    Hey, Glückwunsch!

    Einen Kommentar schreiben:


  • patrickgoll
    antwortet
    So heute war endlich mein Echo Dot in der Post. Ich habe den Skill mit dem Gerät verknüpft. Und siehe da, das funktioniert!

    Ich musste nur noch eine Anpassung machen. Der Skill benötigt eine OAuth Routine, damit das Gerät mit einem Konto verknüpft werden kann. Ich habe mich an diese Anleitung gehalten und habe Amazon selbst als OAuth provider verwendet: http://stackoverflow.com/questions/3...ted-home-skill

    Einziges Problem! Alexa erkennt zwar Geräte und schaltet sie auch. Allerdings liefert sie als Antwort, dass der Befehl für das angegebene Gerät nicht funktioniert. Was gelogen ist, weil es sehr wohl funktioniert.

    Aber damit können wir ja arbeiten

    Einen Kommentar schreiben:


  • patrickgoll
    antwortet
    So Zwischenstatus! Ich habe es hinbekommen mithilfe des Network Plugin als Schnittstelle zu SmartHomeNG und mit der angepassten php App aus dem Edomi Forum meine Lampen zu schalten. Was nicht geht ist dimmen. Ich habe auch rausgefunden warum. Die Kumpels von Edomi können via deren API abfragen welchen Wert eine Lampe/Heizung gerade hat. Dann verrechnen die im Falle eines "IncreasePercentage" Events (also hochdimmen) den alten Wert und fügen einfach sagen wir mal 10 hinzu.

    Da das Network Plugin aber offenbar nur schalten kann und nicht abfragen wird es wohl vorerst nur bei Lampen an und aus bleiben. Mehr werden wir wohl nicht hinbekommen, bis wir sämtliche Komponenten (Network Plugin, Alexa PHP App, ...) angepasst haben.

    Wer mal die "Alpha" testen will kann folgendes tun. Webserver mit Zertifikatsauth einrichten und durch den Router schleifen (setze ich jetzt für die Alpha mal voraus, ein Developer bekommt das schon hin).

    AWS und developer Account machen bei Amazon (Ist auch alles beschrieben im verlinkten EDOMI Thread).

    Dann folgenden Code in einem Texteditor speichern als index.js:

    Code:
    const PORT=xxxx;
    const HOST='domain.de';
    
    
    // namespaces
    const NAMESPACE_CONTROL = "Alexa.ConnectedHome.Control";
    const NAMESPACE_DISCOVERY = "Alexa.ConnectedHome.Discovery";
    
    // errors
    const ERROR_TARGET_OFFLINE = "TargetOfflineError";
    const ERROR_UNSUPPORTED_OPERATION = "UnsupportedOperationError";
    const ERROR_UNEXPECTED_INFO = "UnexpectedInformationReceivedError";
    
    
    // entry
    exports.handler = function (event, context, callback) {
    
        log("Received Directive", JSON.stringify(event));
    
        var postData = JSON.stringify(event);
        fs =    require('fs');
        var options = {
            hostname: HOST,
            port: PORT,
            //family: 6,
            rejectUnauthorized: false,
            path: '/alexa.php',
            method: 'POST',
            //ca: fs.readFileSync('client.crt'),
    
            key:   fs.readFileSync('client.key'),  // Secret client key
            cert:  fs.readFileSync('client.crt'),  // Public client key
    
            headers: {
                'Content-Type': 'application/json',
                'Content-Length': Buffer.byteLength(postData)
            }
        };
    
        var http = require('https');
        var req = http.request(options, (res) => {
            console.log(`STATUS: ${res.statusCode}`);
            console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
            res.setEncoding('utf8');
            var rawData = '';
            res.on('data', (chunk) => rawData += chunk);
            res.on('end', () => {
                console.log('No more data in response.');
                if (rawData.length>0) {
                    log('Response: ', rawData);
                    Data = JSON.parse(rawData);
                    log('json output', JSON.stringify(Data));
    //                callback(null, Data);
                    callback(null, Data);
                } else {
                    callback(null, createError(ERROR_TARGET_OFFLINE) );
                }
                return;
            });
        });
    
        req.on('error', (e) => {
            console.log(`problem with request: ${e.message}`);
            callback(null, createError(ERROR_TARGET_OFFLINE) );
            return;
        });
    
        // write data to request body
        req.write(postData);
        req.end();
        return;
    
    }// exports.handler
    
    
    var handleUnsupportedOperation = function() {
        var header = createHeader(NAMESPACE_CONTROL,ERROR_UNSUPPORTED_OPERATION);
        var payload = {};
        return createDirective(header,payload);
    }// handleUnsupportedOperation
    
    
    var handleUnexpectedInfo = function(fault) {
        var header = createHeader(NAMESPACE_CONTROL,ERROR_UNEXPECTED_INFO);
        var payload = {
            "faultingParameter" : fault
        };
        return createDirective(header,payload);
    }// handleUnexpectedInfo
    
    
    // support functions
    var createMessageId = function() {
        var d = new Date().getTime();
        var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
            var r = (d + Math.random()*16)%16 | 0;
            d = Math.floor(d/16);
            return (c=='x' ? r : (r&0x3|0x8)).toString(16);
        });
        return uuid;
    }// createMessageId
    
    
    var createHeader = function(namespace, name) {
        return {
            "messageId": createMessageId(),
            "namespace": namespace,
            "name": name,
            "payloadVersion": "2"
        };
    }// createHeader
    
    function log(title, msg) {
        console.log(title + ': ' + msg);
    }
    Angepasst werden muss in dieser Datei ganz oben Port und Domain unter dem euer PHP Server hört.
    Ihr zippt das dann als function.zip zusammen mit dem Zertifikat und dem Private Key die client.key und client.crt heißen müssen.
    Der Key muss unverschlüsselt sein.

    Für die PHP Funktion in eurem Server im Rootverzeichnis legt ihr eine Datei an, die alexa.php heißt mit folgendem Inhalt:

    Code:
    <?php
    
    $host = 'ip.von.smart.home';
    $url = '/';
    $configFile = 'config.txt';
    
    function cleanString($string) {
        $string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
        return preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
    }
    
    function readConfig()
    {
        global $koConfig, $configFile;
        $configLines = file($configFile);
        $koConfig=array();
        foreach ($configLines as $line) {
            $line = trim($line);
            if (($line!="") && (substr($line,0,1)!='#') && (substr($line,0,1)!='/') && (substr($line,0,1)!=';')) {
                $subStrings = explode(';', $line);
                if (count($subStrings)>=2) {
                    $name=trim($subStrings[0]);
                    $deviceName=cleanString($name);
                    $koConfig[$deviceName]=array();
                    $koConfig[$deviceName]['name']=$name;
                    for ($i=1; $i<count($subStrings); $i++) {
                        $subStr=trim($subStrings[$i]);
                        if ($subStr=="") continue;
                        if ((is_numeric($subStr)) && (is_int($subStr*1))) {
                            $typ = 'S';
                            $ko = $subStr*1;
                            $koConfig[$deviceName][$typ]=$ko;
                        } else {
                            $subStrings2 = explode(':', $subStr);
                            if (count($subStrings2)==2) {
                                $typ = trim($subStrings2[0]);
                                $ko = trim($subStrings2[1]);
                                $koConfig[$deviceName][$typ]=$ko;
                            }
                        }
                    }
                }
            }
        }
    }
    
    function setValue($koId, $koValue)
    {
        global $url, $host;
        $fp = fsockopen("ip.von.smart.home", port.von.nw.plugin, $errno, $errstr, 30);
        $params=array(
        urlencode('item'),
        urlencode($koId),
        urlencode($koValue)
        );
        if (!$fp) {
            echo "$errstr ($errno)<br />\n";
        } else {
            $out = "GET $url".implode($params, '|')." HTTP/1.1\r\n";
            $out .= "Host: ".$host."\r\n";
            $out .= "Connection: Close\r\n\r\n";
            fwrite($fp, $out);
            $rcv='';
            while (!feof($fp)) { $rcv.=fgets($fp, 128);    }
            fclose($fp);
        }
    }
    
    function getValue($koId)
    {
        global $url, $host;
        $fp = fsockopen("ip.von.smart.home", port.von.nw.plugin, $errno, $errstr, 30);
        $params=array(
        urlencode('login')."=".urlencode('remote'),
        urlencode('pass')."=".urlencode('remote'),
        urlencode('koid')."=".urlencode($koId)
        );
        if (!$fp) {
            echo "$errstr ($errno)<br />\n";
        } else {
            $out = "GET $url?".implode($params, '&')." HTTP/1.1\r\n";
            $out .= "Host: ".$host."\r\n";
            $out .= "Connection: Close\r\n\r\n";
            fwrite($fp, $out);
            $rcv='';
            while (!feof($fp)) { $rcv.=fgets($fp, 128);    }
            fclose($fp);
    
            $pos = strpos($rcv, "\r\n\r\n");
            if ($pos>0) {
                $rcv=substr($rcv,$pos+4);
            } else {
                $pos = strpos($rcv, "\n\n");
                if ($pos>0) $rcv=substr($rcv,$pos+2);
            }
            return $rcv;
        }
    }
    
    function discovery()
    {
        global $koConfig;
    
        $response = array();
        $response['header'] = array();
        $response['header']['namespace']='Alexa.ConnectedHome.Discovery';
        $response['header']['name']='DiscoverAppliancesResponse';
        $response['header']['payloadVersion']="2";
    
        $response['payload'] = array();
        $response['payload']['discoveredAppliances'] = array();
    
        foreach ($koConfig as $koDeviceName => $koData) {
            $type=array();
            $functions=array();
            if (array_key_exists('S', $koData)) { $type[]='Licht'; $functions[]='turnOn'; $functions[]='turnOff'; }
            if (array_key_exists('D', $koData)) { $type[]='Dimmer'; $functions[]='setPercentage'; $functions[]='incrementPercentage'; $functions[]='decrementPercentage'; }
            if (array_key_exists('H', $koData)) { $type[]='Heizung'; $functions[]='setTargetTemperature'; $functions[]='incrementTargetTemperature'; $functions[]='decrementTargetTemperature'; }
    
            $dev = array();
            $dev['applianceId'] = $koDeviceName;
            $dev['manufacturerName'] = 'Patrick';
            $dev['modelName'] = 'Model '.cleanString(implode('', $type));
            $dev['version'] = 'VER01';
            $dev['friendlyName'] = $koData['name'];
            $dev['isReachable'] = true;
            $dev['friendlyDescription'] = implode('/', $type).' im '.$koData['name'].' ('.$koDeviceName.')';
            $dev['actions'] = $functions;
            // 'setTargetTemperature', 'incrementTargetTemperature', 'decrementTargetTemperature', 'setPercentage', 'incrementPercentage', 'decrementPercentage', 'turnOn', 'turnOff'
            $response['payload']['discoveredAppliances'][]=$dev;
        }
        return $response;
    }
    
    
    function control($request)
    {
        global $koConfig, $debugStr;
    
        $device_id = $request['payload']['appliance']['applianceId'];
        $message_id = $request['header']['messageId'];
        $reuqestType = $request['header']['name'];
    
        $response = array();
        $response['header'] = array();
        $response['header']['namespace'] = 'Alexa.ConnectedHome.Control';
        $response['header']['payloadVersion'] = "2";
        $response['header']['messageId'] = $message_id;
    
        $configEntry = $koConfig[$device_id];
    
        // Für Schalter 'S': TurnOnRequest, TurnOffRequest
        if (array_key_exists('S', $configEntry)) {
            if ($reuqestType=='TurnOnRequest') {
                $response['header']['name']='TurnOnConfirmation';
                setValue($configEntry['S'], 1);
            }
            if ($reuqestType=='TurnOffRequest')  {
                $response['header']['name']='TurnOffConfirmation';
                setValue($configEntry['S'], 0);
            }
        }
    
        // Für Dimmer 'D': SetPercentageRequest, IncrementPercentageRequest, DecrementPercentageRequest
        if (array_key_exists('D', $configEntry)) {
            if ($reuqestType=='SetPercentageRequest') {
                $value = $request['payload']['percentageState']['value'];
                $response['header']['name']='SetPercentageConfirmation';
                setValue($configEntry['D'], $value);
            }
            if ($reuqestType=='IncrementPercentageRequest')  {
                $delta = $request['payload']['deltaPercentage']['value'];
                $response['header']['name']='IncrementPercentageConfirmation';
                $oldValue=getValue($configEntry['D']);
                setValue($configEntry['D'], min(100, $oldValue+$delta));
            }
            if ($reuqestType=='DecrementPercentageRequest')  {
                $delta = $request['payload']['deltaPercentage']['value'];
                $response['header']['name']='DecrementPercentageConfirmation';
                $oldValue=getValue($configEntry['D']);
                setValue($configEntry['D'], max(0, $oldValue-$delta) );
            }
        }
    
        // Für Heitung 'H': SetTargetTemperatureRequest / SetTargetTemperatureConfirmation , IncrementTargetTemperatureRequest / IncrementTargetTemperatureConfirmation, DecrementTargetTemperatureRequest / DecrementTargetTemperatureConfirmation 
        if ((array_key_exists('H', $configEntry)) && (($reuqestType=='SetTargetTemperatureRequest') || ($reuqestType=='IncrementTargetTemperatureRequest') || ($reuqestType=='DecrementTargetTemperatureRequest'))) {
            $oldValue=getValue($configEntry['H']);
            $debugStr .= "Oldvalue=$oldValue ";
            $response['payload']=array();
            $response['payload']['temperatureMode']=array('value'=>'AUTO');
            $response['payload']['previousState']=array(
                'mode' => array('value'=>'AUTO'),
                'targetTemperature' => array('value'=>$oldValue),
            );
    
    
            if ($reuqestType=='SetTargetTemperatureRequest') {
                $value = $request['payload']['targetTemperature']['value'];
                $debugStr .= "Setvalue=$value ";
                setValue($configEntry['H'], $value);
                $response['header']['name']='SetTargetTemperatureConfirmation';
            }
            if ($reuqestType=='IncrementTargetTemperatureRequest')  {
                $delta = $request['payload']['deltaTemperature']['value'];
                $response['header']['name']='IncrementTargetTemperatureConfirmation';
                setValue($configEntry['H'], min(100, $oldValue+$delta));
            }
            if ($reuqestType=='DecrementTargetTemperatureRequest')  {
                $delta = $request['payload']['deltaTemperature']['value'];
                $response['header']['name']='DecrementTargetTemperatureConfirmation';
                setValue($configEntry['H'], max(0, $oldValue-$delta) );
            }
            usleep(100*1000);
            $newValue=getValue($configEntry['H']);
            $debugStr .= "newValue=$newValue";
            $response['payload']['targetTemperature']=array('value'=>$newValue);
        }
    
        return $response;
    }
    
    function alexaSystem($request)
    {
        $response = array();
        if ($request['header']['name']=='HealthCheckRequest') {        
            $response['header'] = array();
            $response['header']['messageId']=$request['header']['messageId'];
            $response['header']['name']='HealthCheckResponse';
            $response['header']['namespace']='Alexa.ConnectedHome.System';
            $response['header']['payloadVersion']="2";
            $response['payload'] = array();
            $response['payload']['description'] = 'The system is currently healthy';
            $response['payload']['isHealthy'] = true;
        }
        return $response;
    }
    
    function main()
    {
        global $configFile, $koConfig, $debugStr;
        $fnLog = getcwd() . "/alexa-log.txt";
        date_default_timezone_set('Europe/Berlin');
        $debugStr='';
    
        readConfig();
    
    
        $postdata = file_get_contents("php://input");
    
    
    // For testing....
        if ($postdata=='')
                $postdata = '{"header":{"namespace":"Alexa.ConnectedHome.Discovery","name":"DiscoverAppliancesRequest","payloadVersion":"2","messageId":"2bac165a-e532-4177-86b8-37210f247538"},"payload":{"accessToken":"Atza|IwEBIC096nvP_y5mIaW0H30USLZ3CLDqn6MluMkEU4glt9rLH3E8ufthjUdQtRC1G1FAK6ZNYTJdr3rZw45vLRmy5ETQw-JIaRNFxcylBOVh50a4sohvatpJeLy_SF_Bj-8QKNIwchm6otnbWa_kgQIsS-o9SOt5_l1cxF9TbMHvscw5eSJ0pnulvC145Equx17ldAlGQ9M7tIj8lQO7qHkTZp06jieLbnYvwMHT96kQ6clweB2HVyFqlXPhWjiXlY83GbQdqsNX1WXQm4UfCy3CZ5I8nEKmk0Ju2YVK1UmtgOlx1gNjsvnvA40lqgzXd46s-L3ocZqMB1zfAgO2GUmgFN7R1B3A9wjCgnDJhYRzsxXat_3CsHZ2w0zkeo-g1HJ7vtx2VUqh1W8fM9w93pCEnmLa1Hv1IZCCNqm89xgowqWI-os2QgNjC50QTMYldrFGZo8hzUiRwKvbHRQFVAKiDQ8BtoFHgOG8vizJ_bpbPGLG_JH8ZxSpDpORWuKkKhqoMrplH7mNyrXLCIdK6-LZo9VB"}}';
    
    
        $fp = fopen($fnLog, 'a');
        fwrite($fp, date('r')." =======================================================================================================\n");
        fwrite($fp, date('r')." Request: ".$postdata."\n");
        fwrite($fp, date('r')." -------------------------------------------------------------------------------------------------------\n");
        fclose($fp);
    
        $request = json_decode($postdata, true);
        $response = array();
        if ($request['header']['namespace'] == 'Alexa.ConnectedHome.Discovery') {
            $response = discovery();
        }
        if ($request['header']['namespace'] == 'Alexa.ConnectedHome.Control') {
            $response = control($request);
        }
        if ($request['header']['namespace'] == 'Alexa.ConnectedHome.System') {
            $response = alexaSystem($request);
        }
    
    
        $jsonText = json_encode($response);
    //    include 'prettyprint.php'; $jsonText = prettyPrint($jsonText);
        print $jsonText;  // Eigentliche Rückgabe
    
        $fp = fopen($fnLog, 'a');
        fwrite($fp, date('r')." Response: ".json_encode($response)."\n");
        if ($debugStr!='') {
            fwrite($fp, date('r')." -------------------------------------------------------------------------------------------------------\n");
            fwrite($fp, date('r')." DebugStr: $debugStr\n");
        }
        fwrite($fp, date('r')." =======================================================================================================\n\n");
        fclose($fp);
    }
    
    
    main();
    
    ?>
    Angepasst werden müssen die Stellen ip.von.smart.home und port.von.nw.plugin. Sucht einfach am besten in nem Texteditor danach, bevor ihr den Code als alexa.php abspeichert und passt das auf eure Umgebung an.

    Ebenfalls im Root Verzeichnis des Servers zur alexa.php legt ihr eine config.txt an. meine sieht so aus und sollte selbsterklärend sein:

    Code:
    # Kommentare beginnen mit # oder ; oder // 
    # Format: Name;[Liste von Typen:Item]
    # Typen: S (Lichtschalter), D (Dimmer) oder H (Heizung)
    #
    # Beispiel:     Schlafzimmer Spots; S:EG.Schlafzimmer.Spots.Schalten; D:EG.Schlafzimmer.Spots.Dimmen
    #        Schlafzimmer Heizung; H:EG.Schlafzimmer.Heizung.Wert
    
    Wohnzimmer Deckenlampe; S:EG.Wohnzimmer.Deckenlampe.Schalten; D:EG.Wohnzimmer.Deckenlampe.Dimmen
    Wohnzimmer Ofen; S:EG.Wohnzimmer.SpotsOfen.Schalten; D:EG.Wohnzimmer.SpotsOfen.Dimmen
    Büro Deckenlampe; S:OG.Buero.Deckenlampe.Schalten; D:OG.Buero.Deckenlampe.Dimmen
    Ich habe vorerst mal nur 3 Items drin.
    Ihr müsst in eurer Items.conf dafür natürlich auch das network Plugin freischalten (nw = yes).

    Nun könnt ihr in der AWS Konsole über den Teststring ein Discovery und ein und Ausschaltbefehle senden.

    Code:
    {
      "header": {
        "namespace": "Alexa.ConnectedHome.Discovery",
        "name": "DiscoverAppliancesRequest",
        "payloadVersion": "2",
        "messageId": "06c4efaf-da9b-4deb-8561-54412400382c"
      },
      "payload": {
        "accessToken": "BLA BLA aber brauchen wir nicht(?)"
      }
    }
    Code:
    {
       "header":{
          "namespace":"Alexa.ConnectedHome.Control",
          "name":"TurnOnRequest",
          "payloadVersion":"2",
          "messageId":"81c27978-cc0c-4ae8-b1bc-09510c597a60"
       },
       "payload":{
          "accessToken":"BLA BLA BLA",
          "appliance":{
             "applianceId":"Bro-Deckenlampe",
             "additionalApplianceDetails":{
             }
          }
       }
    }
    Code:
    {
       "header":{
          "namespace":"Alexa.ConnectedHome.Control",
          "name":"TurnOffRequest",
          "payloadVersion":"2",
          "messageId":"81c27978-cc0c-4ae8-b1bc-09510c597a60"
       },
       "payload":{
          "accessToken":"BLA BLA BLA",
          "appliance":{
             "applianceId":"Bro-Deckenlampe",
             "additionalApplianceDetails":{
             }
          }
       }
    }
    Wichtig ist, dass ihr unter "applianceID" die richtige ID einsetzt. Diese erfahrt ihr aus dem Ergebnis der Discovery Abfrage.

    Ich hoffe der ein oder andere kann eventuell nachstellen, was ich hier beschreibe. Dadurch haben wir vielleicht ein bisschen schneller den Source Code verbessert.

    Viel Erfolg beim Testen an alle,

    Grüße Patrick

    Einen Kommentar schreiben:

Lädt...
X