Aplikasi Android untuk Raspberry Pi

Dalam tutorial kami sebelumnya tentang IoT, kami membahas cara mengatur Raspberry Pi dan cara menghubungkannya ke Parse Server menggunakan API Back4App untuk menyimpan objek ke server dan melakukan Query dan Live Query.

Sekarang kita akan membahas cara mereproduksi semua yang dilakukan di sisi Raspberry ke sisi Aplikasi. Dalam tutorial ini, kami menjelaskan Aplikasi Android untuk berinteraksi dengan perangkat IoT yang telah dikonfigurasi sebelumnya. Dari sisi Parse Server, Aplikasi melakukan tugas yang sama dengan Raspberry: menulis objek dan melakukan Query dan Live Query. Harap dicatat bahwa fungsi-fungsi ini mungkin berguna bahkan jika Anda tidak berencana untuk mengembangkan aplikasi IoT!

Parse telah terbukti menjadi kerangka kerja yang luar biasa untuk membuat aplikasi IoT. Pada tahun 2020, dengan penambahan protokol GraphQL API, framework ini menyediakan cara yang lebih baik untuk mengambil data.

Kami menyediakan kode kami sebagai langkah pertama bagi Anda untuk mengembangkan Aplikasi yang Anda inginkan.

Prasyarat

Satu-satunya prasyarat adalah menyelesaikan tutorial Android QuickStart kami. Untuk itu, Anda perlu mengklik tautan yang disebutkan di bawah ini.

https://www.back4app.com/docs/pages/android/how-to-build-an-android-app-on-back4app

Berikut ini adalah tutorial tentang LiveQuery yang akan diperlukan pada bagian 3 dari tutorial Seri IoT ini. Anda tidak harus menyelesaikannya terlebih dahulu.

https://docs.back4app.com/docs/android/live-query/

Jika Anda memiliki pertanyaan selama tutorial ini, Anda dapat menyelesaikannya dengan mengikuti panduan Parse resmi untuk Android di tautan di bawah ini.

http://docs.parseplatform.org/android/guide/

Bagian 1: Dasar-dasar membuat Aplikasi Anda dan terhubung dengan Back4App

Dalam proyek ini, kita menamai kelas kita sebagai “MainActivity.java”. Berikut adalah kode dasar yang akan membantu Anda memulai.

public class MainActivity extends AppCompatActivity {
   @Override
   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
     // Menyisipkan bilah alat pada aplikasi. Penjelasan lebih lanjut tentang bar ini ada di file menu_main_activity.xml 
      Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
      setSupportActionBar(toolbar); 
   }
   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
     // Mengembang menu; ini menambahkan item ke bilah aksi jika ada. 
      getMenuInflater().inflate(R.menu.menu_main_activity, menu);
     mengembalikan nilai true;
   }
   @Override
   public boolean onOptionsItemSelected(MenuItem item) {
     // Menangani klik item bilah aksi di sini. Bilah aksi akan
      // secara otomatis menangani klik pada tombol Home/Up, selama
      // selama Anda menentukan aktivitas induk di AndroidManifest.xml. 
     int id = item.getItemId();
     // tidak ada pemeriksaan SimplifiableIfStatement 
     if (id == R.id.action_settings) {
        mengembalikan nilai true;
      }
      return super.onOptionsItemSelected(item);
   }
}

Anda mungkin perlu menambahkan impor berikut ini:

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
import android.widget.Button;import android.widget.Button;
import android.widget.ToggleButton;
import android.view.View.OnClickListener;

Pada berkas XML tata letak Anda, pastikan Anda menambahkan kode berikut:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android = "http://schemas.android.com/apk/res/android"
   xmlns:app = "http://schemas.android.com/apk/res-auto"
   xmlns:tools = "http://schemas.android.com/tools"
   android:layout_width = "match_parent"
   android:layout_height="match_parent"
   android:id="@+id/myCoordinatorLayout"
   tools:context = "com.example.guilherme.myiotapplication.MainActivity">
   <includelayout = "@layout/konten_kegiatan_utama" />
   <android.support.design.widget.AppBarLayout
      android:layout_width = "match_parent"
      android:layout_height = "bungkus_konten"
      android:theme = "@style/AppTheme.AppBarOverlay">
      <android.support.v7.widget.Toolbar
          android:id = "@+id/toolbar"
          android:layout_width = "match_parent"
          android:layout_height = "bungkus_konten"
          android:background="?attr/colorPrimary"
          app:popupTheme="@style/AppTheme.PopupOverlay" />
   </android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>

Untuk menghubungkan aplikasi Anda ke Back4App, tambahkan kode berikut di bawah ini di dalam fungsi onCreate() pada kelas Anda.

// Menginisialisasi Server Parse
Parse.inisialisasi(new Parse.Configuration.Builder(this)
    .applicationId("YOUR_APP_ID") // dari Pengaturan Inti, pada "Fitur" 
    .clientKey("YOUR_CLIENT_KEY") // dari Pengaturan Inti, pada "Fitur" 
    .server("https://parseapi.back4app.com/")
    .build()
);

Ingatlah untuk mengikuti petunjuk langkah demi langkah di QuickStart untuk memberikan Akses Internet ke aplikasi Anda.

Bagian 2: Menyimpan dan Mengambil Objek pada Parse dan Menampilkan pada Aplikasi

Mulailah dengan menambahkan impor di bawah ini

import com.parse.FindCallback;
import com.parse.Parse;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.SaveCallback;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.List;

Pada bagian ini, kita menyimpan objek dari kelas “CommandGPIO1” dengan sebuah klik tombol. Setiap Objek Parse memiliki tiga atribut default: objectId, createdAt , dan updatedAt. Kelas kita akan memiliki dua atribut tambahan: konten dan tujuan. Nilai untuk konten akan berupa “on” atau “off”, dan merepresentasikan status yang akan dikirim ke LED. Untuk tujuan, semua objek akan berisi “perintah”, tetapi kita dapat mendefinisikan string yang berbeda untuk LED yang berbeda.

Sebagai contoh:

Kita membuat dua tombol, dan masing-masing tombol menulis nilai yang berbeda pada konten. Untuk membuat tombol, tambahkan kode berikut ini ke file XML tata letak Anda:

<Tombol
   android:id = "@+id/tombolKirim"
   android:layout_width = "bungkus_konten"
   android:layout_height = "bungkus_konten"
   android:layout_gravity = "top|start"
   android:layout_marginBottom = "0dp"
   android:layout_marginTop = "120dp"
   android:layout_marginEnd = "0dp"
   android:layout_marginRight = "0dp"
   android:layout_marginKiri = "16dp"
   android:layout_marginStart = "16dp"
   android:text = "Kirim AKTIF"/>

Di dalam berkas kelas Anda, membuat tombol semudah menulis:

Button buttonOn = (Button) findViewById(R.id.buttonSendOn);

Jika Anda seorang pemula dalam pemrograman Android, perlu diketahui bahwa argumen “findViewById” berisi “buttonSendOn”, dan ini adalah Android:Id yang telah kita definisikan pada XML.

Kita ingin tombol ini menyimpan objek pada Parse Server ketika diklik. Untuk melakukannya, tambahkan kode berikut:

buttonOn.setOnClickListener( new OnClickListener(){
   @Override
  public void onClick(final View view) {
     // Membuat objek baru dan memberikan atribut yang tepat 
      ParseObject command = new ParseObject("CommandGPIO1");
      perintah.put("konten","on");
      perintah.put("tujuan", "perintah");
      command.saveInBackground(new SaveCallback(){
      @Menimpa
     public void done(ParseException e){
         Snackbar.make(view, "Dikirim ke Output", Snackbar.LENGTH_LONG )
         .setAction("Action", null).show();
      }
   }); 
});

Perhatikan, kita dapat menambahkan fungsi apa pun yang kita inginkan untuk dijalankan di dalam fungsi callback onClick. Di sini, kita membuat objek kelas “CommandGPIO1”, menetapkan konten sebagai “on”, dan tujuan sebagai “command”.

Perlu diketahui bahwa kita TIDAK perlu mendefinisikan kelas ini sebelumnya di dasbor Parse! Jika nanti Anda memilih untuk menambahkan atribut baru, atau mengubah nama kelas Anda, maka Anda hanya perlu mengerjakan kode Anda, dan perubahannya akan diperbarui secara otomatis di dasbor.

Pada titik ini, Anda sebaiknya menguji aplikasi Anda dan memeriksa apakah objeknya sudah dibuat!

SaveCallback menampilkan sebuah snackbar, yang merupakan umpan balik ringan di bagian bawah layar Anda, seperti yang ditunjukkan pada gambar di atas.

Salin kode ini untuk membuat tombol yang menulis objek dengan “off”. Ubah baris-baris berikut pada XML tata letak

android:id = "@+id/tombolKirimMati"
android:layout_gravity = "top|center"
android:layout_marginKiri = "0dp"
android:layout_marginStart = "0dp"
android:text = "Kirim MATI"/>

Buat tombol baru dan ubah baris tempat konten ditulis:

Button buttonOff = (Button) findViewById(R.id.buttonSendOff);
command.put("konten","off");

Sekarang setelah semuanya bekerja dengan baik di Parse Server, kita ingin memberikan umpan balik permanen kepada pengguna aplikasi. Untuk itu, kita akan menggunakan elemen EditText, seperti yang ditunjukkan di bawah ini.

Definisikan elemen ini pada XML tata letak:

<EditText
    android:id = "@+id/status1Text"
    android:layout_width = "bungkus_konten"
    android:layout_height = "bungkus_konten"
    android:layout_gravity = "top|start"
    android:maxLines = "2"
    android:ems = "10"
    android:singleLine = "false"
    app:layout_behavior = "@string/appbar_scrolling_view_behavior" />

Di dalam lingkup onCreate() kelas Anda, tambahkan kode berikut:

// Mendefinisikan elemen teks untuk menampilkan status pin output, yang menerima perintah dari aplikasi
// Perintah dikirim oleh tombol, yang nantinya akan dijelaskan pada kode ini.
final EditText textOutPin = (EditText) findViewById(R.id.status1Text);
textOutPin.setFocusable(false);
textOutPin.setClickable(true);
textOutPin.setText("Memuat status pin output...");

Baris pertama membuat objek. Baris kedua membuatnya tidak dapat diedit oleh pengguna. Baris ketiga membuatnya dapat diklik, sehingga dapat disalin dan ditempel. Baris keempat menetapkan teks awal.

Kita ingin menulis bidang konten dari objek “CommandGPIO1” terakhir yang disimpan pada Parse ke objek EditText ini. Meskipun kita dapat melakukan ini dengan menggunakan beberapa logika di dalam kode, kita akan mengambil objek dari Parse dengan melakukan ParseQuery karena ini memberikan hasil yang lebih realistis dan kuat.

Kode di bawah ini mendeklarasikan, mengatur parameter, dan mencetak hasil dari Parse Query.

ParseQuery<ParseObject> queryOut = ParseQuery.getQuery("CommandGPIO1");
queryOut.whereEqualTo("tujuan", "perintah");
queryOut.addDescendingOrder("createdAt");
queryOut.setLimit(1);
queryOut.findInBackground(new FindCallback<ParseObject>() {
   @Override
  public void done(List<ParseObject> objects, ParseException e) {
     if (e == null){
         textOutPin.setText("Output adalah " + objects.get(0).getString("content"));
      }
     else {
         textOutPin.setText("Error: " + e.getMessage());
      }
   }
});

Baris pertama membuat kueri. Baris kedua menambahkan batasan untuk memilih hanya objek-objek yang bidang tujuannya berisi “perintah”. Baris ketiga mengurutkan objek-objek mulai dari yang terbaru. Baris keempat membatasi hasil menjadi satu, memastikan bahwa kita akan mengambil objek terbaru.

Baris kelima mengaktifkan kueri, dan memanggil fungsi callback ketika selesai. Di sini, kita menulis konten objek yang diambil ke objek EditText yang telah didefinisikan sebelumnya.

Kita akan menambahkan potongan kode tersebut tepat setelah mendeklarasikan objek EditText, sehingga kueri dilakukan ketika aplikasi terbuka, dan juga di SaveCallback ketika menyimpan objek baru di Parse, untuk memperbarui teks secara otomatis ketika membuat objek baru.

Pada titik ini, aplikasi Anda seharusnya bekerja seperti yang diilustrasikan dalam tangkapan layar berikut.

Terakhir, kita tambahkan tombol refresh untuk memungkinkan pengguna melakukan kueri di atas kapan pun mereka mau. Ini akan dilakukan dengan gaya tombol yang berbeda, yaitu Floating Action Button.

Tambahkan kode ini ke dalam file XML layout:

<android.support.design.widget.FloatingActionButton
    android:id = "@+id/fab"
    android:layout_width = "bungkus_konten"
    android:layout_height = "bungkus_konten"
    android:layout_gravity = "top|end"
    android:layout_marginBottom="0dp"
    android:layout_marginTop = "120dp"
    android:layout_marginEnd = "16dp"
    android:layout_marginRight = "16dp"
    android:layout_marginKiri = "0dp"
    android:layout_marginStart = "0dp"
    app:srcCompat="@android:drawable/ic_popup_sync" />

Sekarang, di dalam lingkup onCreate() di dalam kelas, tambahkan kode berikut:

// Tombol Refresh untuk mendapatkan status keluaran ketika diminta.
// Kueri yang sama seperti yang pertama dilakukan di sini
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener(){
    @Override
   public void onClick(final View view){
        ParseQuery<ParseObject> queryOut = ParseQuery.getQuery("CommandGPIO1");
        queryOut.whereEqualTo("tujuan", "perintah");
        queryOut.addDescendingOrder("createdAt");
        queryOut.setLimit(1);
        queryOut.findInBackground(new FindCallback<ParseObject>() {
            @Override
           public void done(List<ParseObject> objects, ParseException e) {
              if (e == null){
                   textOutPin.setText("Output adalah " + objects.get(0).getString("content"));
               }
              else {
                   textOutPin.setText("Error: " + e.getMessage());
               }
               Snackbar.make(view, "Status Output yang diperbarui", Snackbar.LENGTH_LONG ).setAction("Action", null).show();
            }
        });
     }
 });

Pada titik ini kita sekarang dapat menyimpan objek di Parse Server, mengambil informasi darinya dan menampilkannya di aplikasi Anda! Aplikasi Anda seharusnya bekerja seperti yang ditunjukkan pada gambar di bawah ini:

Bagian 3: Mendengarkan Peristiwa Waktu Nyata Menggunakan Live Query dan Menampilkan di Aplikasi

Pada bagian ini, kita akan memonitor secara real-time kelas “InputGPIO” di Dasbor Parse, dan menampilkan “konten” dari objek-objek tersebut untuk pengguna.

Mulailah dengan mendefinisikan EditText baru dalam XML tata letak:

<EditText
    android:id = "@+id/status2Text"
    android:layout_width = "bungkus_konten"
    android:layout_height = "bungkus_konten"
    android:layout_gravity = "center|start"
    android:layout_marginBottom = "0dp"
    android:maxLines ="2"
    android:ems = "10"
    android:singleLine = "false"
    app:layout_behavior = "@string/appbar_scrolling_view_behavior" />

Dalam lingkup onCreate(), buat objek EditText baru dan lakukan kueri inisialisasi (belum ditayangkan) segera setelahnya.

final EditText textInPin = (EditText) findViewById(R.id.status2Text);
textInPin.setFocusable(false);
textInPin.setClickable(true);
textInPin.setText("Memuat status pin input...");
// Kueri awal (tidak langsung) untuk mendapatkan status pin yang terakhir disimpan
ParseQuery<ParseObject> queryIn = ParseQuery.getQuery("InputGPIO");
queryIn.whereEqualTo("type", "interrupt");
queryIn.addDescendingOrder("createdAt");
queryIn.setLimit(1);
queryIn.findInBackground(new FindCallback<ParseObject>() {
    @Override
   public void done(List<ParseObject> objects, ParseException e) {
       if (e == null){
            textInPin.setText("Input adalah " + objects.get(0).getString("content"));
        }
       else {
            textInPin.setText("Kesalahan: " + e.getMessage());
        }
    }
});

Perhatikan bahwa atribut “InputGPIO” adalah konten dan tipe, yang terakhir berperan sebagai tujuan pada kelas “CommandGPIO”.

Pada titik ini, aplikasi Anda seharusnya terlihat seperti gambar yang ditunjukkan di bawah ini.

Sekarang kita akan mengimplementasikan Live Query. Tutorial yang dirujuk sebelumnya diperlukan di sini.

https://docs.back4app.com/docs/android/live-query/

Pastikan Anda mengikuti langkah 1 dalam tutorial Live Query untuk memilih kelas mana yang akan diaktifkan Live Query dan menentukan nama subdomain. Anda mungkin perlu membuat kelas “InputGPIO” (jika belum ada) untuk mengaktifkan fitur tersebut. Ikuti langkah 2 dalam tutorial untuk menyiapkan klien Live Query di Android.

Ingatlah untuk menambahkan impor berikut ini:

import tgio.parselivequery.BaseQuery;
import tgio.parselivequery.LiveQueryClient;
import tgio.parselivequery.LiveQueryEvent;
import tgio.parselivequery.Subscription;
import tgio.parselivequery.interfaces.OnListener;

Tambahkan kode berikut untuk menginisialisasi LiveQuery dan mendefinisikan parameternya.

// Menginisialisasi Live Query
LiveQueryClient.init("wss:YOUR_SUBDOMAIN_NAME.back4app.io", "YOUR_APP_ID", true );
LiveQueryClient.connect();
// Mendefinisikan atribut dari LiveQuery 
 Langganan subIn = new BaseQuery.Builder("InputGPIO")
    .where("type","interrupt")
    .addField("content")
    .build()
    .subscribe();

Ketika mendefinisikan langganan, kita hanya mengambil elemen-elemen yang atribut jenisnya adalah “interrupt” dan mengambil konten field.

Sekarang, tambahkan kode berikut ini untuk merespons setiap kali objek yang didefinisikan oleh langganan dibuat di Parse Server.

// Mulai mendengarkan peristiwa LiveQuery CREATE, mendapatkan konten dan tulisannya
subIn.on(LiveQueryEvent.CREATE, new OnListener() {
    @Override
   public void on(JSONObject object) {
       try {
           final String subInContent = (String) ((JSONObject) object.get("object")).get("content");
            runOnUiThread(new Runnable() {
                @Override
               public void run() {
                   textInPin.setText("Input adalah " + subInContent);
                   Snackbar.make(findViewById(R.id.myCoordinatorLayout), "Input pin diubah menjadi " + subInContent.toUpperCase(), Snackbar.LENGTH_LONG ).setAction("Action", null).show();
                }
            });
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
});

Bidang konten objek akan ditampilkan dalam elemen EditText baru kita.

Apa yang telah kita lakukan pada saat ini sudah cukup untuk menampilkan input apa pun yang dikirim oleh perangkat IoT. Namun, untuk memverifikasi bagaimana aplikasi bekerja, kita akan mengimplementasikan jenis tombol lain, yaitu Tombol Toggle yang akan membuat objek kelas “InputGPIO” dan menyimpannya di Parse Server.

Tambahkan kode berikut ini ke file XML layout:

<ToggleButton
    android:id = "@+id/toggleTest"
    android:layout_width = "bungkus_konten"
    android:layout_height = "bungkus_konten"
    android:layout_gravity = "center|end"
    android:layout_marginBottom = "0dp"
    android:layout_marginTop = "100dp"
    android:layout_marginEnd = "0dp"
    android:layout_marginRight = "0dp"
    android:layout_marginKiri = "0dp"
    android:layout_marginStart = "0dp"
    android:textOn = "masukan aktif"
    android:textOff = "input mati"/>

Tambahkan kode yang disebutkan di bawah ini di dalam lingkup fungsi onCreate(), di kelas MainActivity.

// Tombol Toggle di sini hanya untuk meniru objek yang akan dibuat oleh perangkat keras
ToggleButton toggleTest = (ToggleButton) findViewById(R.id.toggleTest);
toggleTest.setOnClickListener( new OnClickListener(){
    @Override
   public void onClick(final View view) {
        ParseObject perintah = new ParseObject("InputGPIO");
       if(gpioStatusTest.equals("off"))
           gpioStatusTest = "on";
       else
            gpioStatusTest = "off";
        command.put("type","interrupt");
        command.put("content", "From Toggle: " + gpioStatusTest);
        command.saveInBackground(new SaveCallback(){
            @Override
           public void done(ParseException e){
                Snackbar.make(view, "Mengubah pin input", Snackbar.LENGTH_LONG ).setAction("Action", null).show();
            }
        });
    }
});

Juga, deklarasikan String dalam lingkup MainActivity.

String gpioStatusTest = "off";

Kita sudah selesai dengan aplikasi! Di akhir tutorial ini, aplikasi Anda akan terlihat sangat mirip dengan gambar yang ditunjukkan di bawah ini.

Jika Anda ingin terus mengembangkan aplikasi IoT kami, silakan baca Seri IoT kami, panduan langkah demi langkah, yang mengajarkan Anda dasar-dasar untuk menyiapkan Raspberry Pi dan aplikasi tertentu, seperti mengambil dan menyimpan objek dari Parse Server menggunakan JavaScript.

Kode kami tersedia di tautan berikut:

https://github.com/back4app/iot-raspberry-node

Referensi

Menghubungkan Raspberry Pi ke Parse Server

Menyiapkan Raspberry Pi

Bagaimana cara menghubungkan aplikasi Android dengan perangkat IoT?

Bagian 1: Dasar-dasar pembuatan Aplikasi dan koneksi dengan sisi server.
Bagian 2: Menyimpan dan Mengambil Objek saat Parse dan Menampilkannya di Aplikasi.
Bagian 3: Mendengarkan Peristiwa Real-Time Menggunakan Live Query dan Menampilkannya di Aplikasi


Leave a reply

Your email address will not be published.