Einfaches Codebeispiel Java/Android Set Lampe on / Lampe off ?

Begonnen von jmbtlb1, 27 Dezember 2018, 12:09:18

Vorheriges Thema - Nächstes Thema

rudolfkoenig

ZitatDa da kann doch eigentlich nicht viel fehlen ?
Doch :)
8083 klingt nach HTTP, und das ist _kein_ "plain TCP/IP", d.h. man muss nach dem Regeln spielen, HTTP Header schicken, usw.


vbs

Genau genommen heißt nur die Variable "Websocket". Woher die Klasse "Socket" kommt, kann man nicht wissen.

Werner Schäffer

Zitat von: vbs am 05 Januar 2019, 19:33:17
Genau genommen heißt nur die Variable "Websocket". Woher die Klasse "Socket" kommt, kann man nicht wissen.

das hatte ich mir auch schon gedacht nachdem ich meinen Post abgeschickt hatte und deshalb kann man diese Codeschnipsel nur wirklich beurteilen wenn auch die eingesetzten Pakete angegeben sind. Also Michael - du bist gefordert.

Werner Schäffer

ich will das noch präzisieren:

Miachael - welches Paket nutzt der Befehl "new Socket"?

Werner Schäffer

Michael noch ein Ratschlag:
vergiss einfach telnet für dein Anliegen, weil ...


  • telnet eine Anwendung ist, wie Rudolf hier schon sagte, die TCP-Verbindungen auf Basislevel ermöglicht. Dies ist sehr schön, sollte aber nur auf localhost benutzt werden. Schon lange meldet sich ein eingermaßen kompetenter Mensch mehr mit telnet an einem System an. Man benutzt dafür ssh, aber das ist was ganz Anderes und erfordert entsprechende Infrastruktur. Hinzu kommt dass viele Standardeinstellungen auf Linux verhindern dass du mit native telnet überhaupt reinkommst.

  • nimm besser http-Requests, da gibt es in Android/Java Standardpakete und fhem kann da auch qualifiziert liefern (soweit ich weiß - müssen Andere sich äußern)

  • willst du mit Websockets arbeiten, brauchst du eine Schnittstelle die das unterstützt (z.B. fhem.js - sorry für die Eigenwerbung)

jmbtlb1

Guten Morgen zusammen
erstmal vielen Dank für die Antworten an alle.

Vielleicht unterschätzte ich da die Komplexität meines Wunsches , da Java für mich Neuland ist.
Ich programmiere seit über 40 Jahren , Sicherheitsaspekte sind mir nicht ganz neu.

Ob die Verbindung über Telnet , HTTP oder über Buschtrommel übertragen wird ist mit eigentlich egal , da bin ich flexibel :), dazu weiß ich noch zuwenig über Java.

Meine Hoffnung  war , dass man da nur eine handvoll Codezeilen braucht, damit es klick macht
Falls ich da auf dem Holzweg bin und man seitenlangen Code braucht , wäre das auch ein Hinweis.

Also wie kriege ich "set WZ_Lampe_Fenster on" von Android aus gesteuert, egal wie , egal wie sicher, egal welcher Ansatz ?

Es soll wirklich nur als Verständnis Beispiel dienen , es soll keine komplexe Anwendung werden, sondern nur einmal im lokalen Netzwerk klick machen , das wäre schon Klasse.

Gruß & Danke
Michael

Werner Schäffer

Versuch doch mal


       try {
            URL url = new URL("http://fhem.fritz.box:8083/fhem?XHR=1&fwcsrf=csrf_233137639685367&cmd=" + URLEncoder.encode("set Lampe on", "UTF-8"));
            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
            httpConn.disconnect();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


Es wird noch das CSRFTOKEN gebraucht (Parameter fwcsrf). Dies findest du im Fhem (Einheit FHEMWEB). Aber Achtung: dieses Token ändert sich bei jedem Neustart von Fhem. Es gibt hier im Forum genug Beiträge die dieses Problem behandeln.

jmbtlb1


Ich habe das CSR Token zum Testen mal abgeschaltet.

Fhem läuft bei mir auf einem Raspberry mit fester IP an der Fritzbox

URL url = new URL("http://192.168.178.48:8083/fhem?XHR=1&cmd=" + URLEncoder.encode("set WZ_Lampe_Tisch on", "UTF-8"));

Es gibt keine Fehlermeldung , aber es schaltet auch nicht


       

Werner Schäffer

Bei mir hat dies funktioniert.

Deshalb kann ich nur noch Folgendes fragen:
- funktioniert der Schalter wenn du die URL aus dem Javaprogramm in einem Browser eingibst?
- hast du schon in FHEM "set globals verbose 5" gesetzt und dann die Fhem-Logfiles angeschaut?
- hast du schon einen Blick in den Android Logcat geworfen?

jmbtlb1


Wenn ich über einen Browser gehe schaltet die Lampe ein
Siehe Script
Den Java Logcat schaue ich mir noch an

2019.01.08 06:20:07 5: HMLAN_Parse: HMLAN1 V:03C5 sNo:JEQ0706378 d:1EA186 O:1EA186 t:2462B1AC IDcnt:0013 L:2 %
2019.01.08 06:20:07 5: Starting notify loop for HMLAN1, 1 event(s), first is loadLvl: low
2019.01.08 06:20:07 5: End notify loop for HMLAN1
2019.01.08 06:20:17 4: Connection accepted from WEB_192.168.178.21_53941
2019.01.08 06:20:17 4: Connection accepted from WEB_192.168.178.21_53942
2019.01.08 06:20:17 4: WEB_192.168.178.21_53941 GET /fhem?cmd=set%20WZ_Lampe_Tisch%20on; BUFLEN:0
2019.01.08 06:20:17 5: Cmd: >set WZ_Lampe_Tisch on<
2019.01.08 06:20:17 5: CUL_HM WZ_Lampe_Tisch protEvent:CMDs_pending pending:1
2019.01.08 06:20:17 5: Starting notify loop for WZ_Lampe_Tisch, 1 event(s), first is set_on
2019.01.08 06:20:17 5: End notify loop for WZ_Lampe_Tisch
2019.01.08 06:20:17 3: CUL_HM set WZ_Lampe_Tisch on
2019.01.08 06:20:17 5: HMLAN_Send:  HMLAN1 S:S2BE77E51 stat:  00 t:00000000 d:01 r:2BE77E51 m:E3 A011 1EA186 41B2C6 0201C80000
2019.01.08 06:20:17 5: CUL_HM WZ_Lampe_Tisch protEvent:CMDs_processing... pending:0
2019.01.08 06:20:17 4: WEB_192.168.178.21_53941 GET /fhem?fw_id=; BUFLEN:0
2019.01.08 06:20:17 4: WEB: /fhem?fw_id= / RL:1540 / text/html; charset=UTF-8 / Content-Encoding: gzip

Werner Schäffer

ich meinte eigentlich:

set globals verbose 5
dann Android Anwendung ausführen und schauen ob was im FHEM-Log steht
wenn ja - analysieren
wenn nein - dann hilft nur Android Logcat

jmbtlb1

Aus der App heraus scheint nichts beim fhem anzukommen

public class fhemTest extends AppCompatActivity {

    Button btnLicht;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fhem_test);

        final Button Licht = findViewById(R.id.btnLicht);
        Licht.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    //URL url = new URL("http://fhem.fritz.box:8083/fhem?XHR=1&fwcsrf=csrf_233137639685367&cmd=" + URLEncoder.encode("set Lampe on", "UTF-8"));
                    URL url = new URL("http://192.168.178.48:8083/fhem?XHR=1&cmd=" + URLEncoder.encode("set WZ_Lampe_Tisch on", "UTF-8"));
                    HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
                    httpConn.disconnect();
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Licht.setText("An");
            }
        });
    }
}

Beim drücken des Buttons erscheint im Logcat

01-08 22:15:49.226 26663-26663/com.example.michael.fhemtest W/art: Failed execv(/system/bin/dex2oat --runtime-arg -classpath --runtime-arg  --debuggable --instruction-set=arm64 --instruction-set-features=smp,a53 --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=generic --instruction-set-features=default --dex-file=/data/app/com.example.michael.fhemtest-1/split_lib_slice_8_apk.apk --oat-file=/data/dalvik-cache/arm64/data@app@com.example.michael.fhemtest-1@split_lib_slice_8_apk.apk@classes.dex) because non-0 exit status

01-08 22:15:49.228 26663-26663/com.example.michael.fhemtest W/System: ClassLoader referenced unknown path: /data/app/com.example.michael.fhemtest-1/lib/arm64

01-08 22:15:49.234 26663-26663/com.example.michael.fhemtest I/InstantRun: starting instant run server: is main process

01-08 22:15:49.299 26663-26663/com.example.michael.fhemtest I/HwCust: Constructor found for class android.app.HwCustHwWallpaperManagerImpl

01-08 22:15:49.325 26663-26663/com.example.michael.fhemtest W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter
android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable

01-08 22:15:49.515 26663-26663/com.example.michael.fhemtest I/HwSecImmHelper: mSecurityInputMethodService is null

01-08 22:15:49.599 26663-26715/com.example.michael.fhemtest E/HAL: load: id=gralloc != hmi->id=gralloc
01-08 22:15:49.599 26663-26715/com.example.michael.fhemtest I/OpenGLRenderer: Initialized EGL, version 1.4
01-08 22:15:49.660 26663-26663/com.example.michael.fhemtest W/art: Before Android 4.1, method int android.support.v7.widget.DropDownListView.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView

01-08 22:15:49.690 26663-26663/com.example.michael.fhemtest I/HwSecImmHelper: mSecurityInputMethodService is null

Werner Schäffer

offensichtlich ist damit dass dein Android Programm gar keine Befehle sendet
also musst du dich mit Android-Java auseinandersetzen und schauen warum da nichts rausgeht  ...
ein Tipp noch: schließ ein Android-Gerät mit USB an deinen Rechner und teste nicht mit Android-Emulatoren
setze im Java-Code Befehle ab : Log.i("woistdermist","so einmist");  und suche im Logcat danach

jmbtlb1

So , heiter geht's weiter :)
1. Die im Code eingebauten Log Texte werden angezeigt
2. Die erzeugte URL funktioniert im Browser

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fhem_test);
        final Button Licht = findViewById(R.id.btnLicht);
        Licht.setText("Vor Click");
        Licht.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    Log.i("Vor URL", "Vor URL: ");
                    URL url = new URL("http://192.168.178.48:8083/fhem?XHR=1&cmd=" + URLEncoder.encode("set WZ_Lampe_Fenster on", "UTF-8"));
                    HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
                    Log.i("Vor disconnect", "Vor disconnect ");
                    httpConn.disconnect();
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Log.i("Try Ende", "Try Ende ");
                Licht.setText("Licht an Sofa");
            }


Im Logcat findet sich folgendes:

01-14 19:00:50.073 13247-13247/com.example.michael.fhemtest I/HwSecImmHelper: mSecurityInputMethodService is null
01-14 19:00:50.157 13247-13247/com.example.michael.fhemtest I/Vor URL: Vor URL:
01-14 19:00:50.157 13247-13247/com.example.michael.fhemtest I/Vor disconnect: Vor disconnect
01-14 19:00:50.157 13247-13247/com.example.michael.fhemtest I/Try Ende: Try Ende

Die erzeugte URL
com.android.okhttp.internal.huc.HttpURLConnectionImpl:http://192.168.178.48:8083/fhem?XHR=1&cmd=set+WZ_Lampe_Fenster+on

funktioniert im Browser

Müssen noch Berechtigungen gesetzt werden  ?

Werner Schäffer

Hast du in dem Manifest für deine App das Recht für Internet vergeben?
Wie das geht weiß Google.