Glowing up LED using PHP and FCM using Android Things NXP Pico i.MX7D

Android Things

Hello Friends, In our previous article we have learned How to Blink and LED using UI button on the display. We have also learned How to blink an LED without any UI button.

In this tutorial, we are going to create a program which will operate a LED over the internet using Android Things NXP Pico i.MX7D.

Here we will follow several steps of Internet Of Things (IOT) on this Android Things project.

1. We will send some data from our smartphone device using a simple android app.

2. We will receive that data from our server.

3. According to the received data the server will send some auto response using Firebase Cloud Messaging system.

4. According to the received response in our Android Things NXP Pico. We will write down the code that will On/Off our LED.

We will use PHP as our server side programming language to receive the data and generate the response (using FCM).

We have to use Firebase Cloud Messaging as there is no notification bar in the Android Things NXP Pico i.MX7D. We are using global topic messaging instead of  single device messages.

1. Hardware Requirements: 

i) Android Things NXP Pico Starter kit

ii) Breadboard 

ii) LED

iii) Connecting Wires

We added two wires with the LED and nxp pico board GPIO. We added ground number 6 with the led and GPIO6_IO12 as VCC. 

Note: As we can see, the GPIO6 series is giving high voltage, other gpio is giving low voltage. I don't know the reason, but mentioned here because of your doubt.

We have added the positive part of the LED with gpio and negative part of the led with the ground using the connecting wires.

2. Software Requirements:

For this project we have to use one server side programming language, for this case We are using PHP. We need to use Firebase Cloud Messaging to deliver instant messages to the app. 

For Firebase, we have used a great tutorial from Androidhive.

To use Firebase, you have to create a project to the firebase console.

To create firebase project, we will do the following steps

Next, after creating the new peoject we are going to add one android app to our project and then we are going to follow these steps

From this screen we will get our firebase api key, now we will create some php script to send firebase cloud messages to our android things app. 

3. Setup the server side scripts to receive the data and generate the response

> First Create a Folder named Firebase inside your project

> Then inside that folder create 3 files with the name Config.php, Push.php  and Firebase.php

> Those are the setup files for Firebase Cloud Messaging System.

Config.php

<?php
// Firebase API Key
define('FIREBASE_API_KEY', '<Your API Key>');
?>

Config.php is the basic configuration file for the FCM. Just replace the <Your API Key> with your firebase server key. After that lets jump into Push.php file

Push.php

<?php
/**
 * @author Ravi Tamada
 * @modified Som Sankar Naskar
 * @link URL Tutorial link
 */
class Push {

    // push message title
    private $title;
    private $message;
    private $data;

    function __construct() {
        
    }

    public function setTitle($title) {
        $this->title = $title;
    }

    public function setMessage($message) {
        $this->message = $message;
    }

    public function setPayload($data) {
        $this->data = $data;
    }


    public function getPush() {
        $res = array();
        $res['data']['title'] = $this->title;
        $res['data']['message'] = $this->message;
        $res['data']['timestamp'] = date('Y-m-d G:i:s');
        return $res;
    }
}
?>

Push class is mainly used here as a setter class. It receives all the title, message and image as a payload which is later becomes easy to use the data. Now create the Firebase class in Firebase.php which is the main class of Firebase Cloud Messaging System.

Firebase.php

<?php
/**
 * @author Ravi Tamada
 * @modified Som Sankar Naskar
 * @link URL Tutorial link
 */
class Firebase {

    // Sending message to a topic by topic name
    public function sendToTopic($to, $message) {
        $fields = array(
            'to' => '/topics/' . $to,
            'data' => $message,
        );
        return $this->sendPushNotification($fields);
    }

    // function makes curl request to firebase servers
    private function sendPushNotification($fields) {
        
        require_once __DIR__ . '/config.php';

        // Set POST variables
        $url = 'https://fcm.googleapis.com/fcm/send';

        $headers = array(
            'Authorization: key=' . FIREBASE_API_KEY,
            'Content-Type: application/json'
        );
        // Open connection
        $ch = curl_init();

        // Set the url, number of POST vars, POST data
        curl_setopt($ch, CURLOPT_URL, $url);

        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        // Disabling SSL Certificate support temporarly
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));

        // Execute post
        $result = curl_exec($ch);
        if ($result === FALSE) {
            die('Curl failed: ' . curl_error($ch));
        }

        // Close connection
        curl_close($ch);

        return $result;
    }
}
?>

In Firebase class there are 2 methods sendToTopic() and sendPushNotification(). The sendToTopic() method will receive the message and whom to send, Then it calls the sendPushNotification() method which receives the data and uses PHP curl to send the response which sends the data into into Android Things NXP Pico.

Now we are going to create one last script(php file) where I can send data from our MobileApp. And this code will give the data to the Android Things App.

So now come outside the Firebase folder then make a file named as GlowLed.php. This is the main file in which we will include all the classes and we will make our own push function which will receive the title, message and image(if required) as parameters then we will send the data as json response through the FCM system which we have just created inside the Firebase folder.

GlowLed.php

<?php
//User Defined function will be here
require_once 'Firebase/Config.php';
require_once 'Firebase/Push.php';
require_once 'Firebase/Firebase.php';

function sendPush($title='',$message='',$image=false) {
    $firebase = new Firebase();
    $push = new Push();
    $push_type = 'topic';
    $push->setTitle(html_entity_decode($title));
    $push->setMessage($message);
    
    $json = $response = '';

    if ($push_type == 'topic') {
        $json = $push->getPush();
        $response = $firebase->sendToTopic('global', $json);
    }
    
    return true;
}
if(isset($_GET['state']))
	sendPush('',$_GET['state']);
?>

Till this portion we have done our server setup for our project perfectly. Now we have to do 2 things to complete our project. 

> Code Setup for our Android Things NXP Pico
> Code Setup for our Android Mobile App 

4. Android Studio Code For Android Things NXP Pico i.MX7D

Now we are giving the code of Android Things App. First we will create one project for Android Things, then we need to create to Services named MyFirebaseMessagingService and MyFirebaseInstantIdService. We have to add those to the manifest.

<service
    android:name=".MyFirebaseInstanceIDService">
    <intent-filter>
        <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
    </intent-filter>
</service>
<service
    android:name=".MyFirebaseMessagingService">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>

We need to add some permission to our app

<uses-permission android:name="com.google.android.things.permission.USE_PERIPHERAL_IO" />
<uses-permission android:name="android.permission.INTERNET"/>

> Here is the full code of AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.sodiarc.lightautomationiot">
    <uses-permission android:name="com.google.android.things.permission.USE_PERIPHERAL_IO" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <application>
        <uses-library android:name="com.google.android.things" />

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.IOT_LAUNCHER" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>

        </activity>
        <service
            android:name=".MyFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>
        <service
            android:name=".MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>
    </application>

</manifest>

> This is our MyFirebaseMessagingService code

package com.sodiarc.lightautomationiot;

import android.util.Log;

import com.google.firebase.messaging.FirebaseMessagingService;
import com.google.firebase.messaging.RemoteMessage;

import org.json.JSONObject;

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private static final String TAG = MyFirebaseMessagingService.class.getSimpleName();
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Log.d(TAG, "From: " + remoteMessage.getFrom());
        Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        try {
            JSONObject reader = new JSONObject(remoteMessage.getData().toString());
            JSONObject data = reader.getJSONObject("data");
            String msg = data.getString("message");
            Log.d("message",msg);
            MainActivity.fire(msg);
        } catch(Exception e) {
            Log.d("Error",""+e);
        }

    }
}

> This is our MyFirebaseInstantIdService code

package com.sodiarc.lightautomationiot;

import android.util.Log;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {
    private static final String TAG = MyFirebaseInstanceIDService.class.getSimpleName();
    @Override
    public void onTokenRefresh() {
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);
    }
}

> This is our MainActivity Code

package com.sodiarc.lightautomationiot;

import android.app.Activity;
import android.os.Bundle;
import com.google.android.things.pio.Gpio;
import com.google.android.things.pio.PeripheralManager;
import com.google.firebase.messaging.FirebaseMessaging;

public class MainActivity extends Activity {
    private static final String TOPIC_GLOBAL = "global";
    private static Gpio mLedGpio;
    public static final String LED_PIN_NAME = "GPIO6_IO13";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        PeripheralManager manager = PeripheralManager.getInstance();
        try {
            mLedGpio = manager.openGpio(LED_PIN_NAME);
            mLedGpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW);
        } catch (Exception e) {}

        FirebaseMessaging.getInstance().subscribeToTopic(TOPIC_GLOBAL);
    }

    public static void fire(String msg) {

        int status = Integer.parseInt(msg);

        try {
            if (status == 1)
                mLedGpio.setValue(true);
            else
                mLedGpio.setValue(false);
        } catch (Exception e) {}
    }
}

5. Android Studio Code For Android Mobile App

Here we go, our basic android mobile app, which can control the LED connected to the Android Things. 

> activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/on"
        android:onClick="toggleLed"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="@color/colorOpen"
        android:textColor="@color/colorText"
        android:text="On"/>
    <Button
        android:id="@+id/off"
        android:onClick="toggleLed"
        android:layout_marginTop="20dp"
        android:layout_below="@id/on"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="@color/colorClose"
        android:textColor="@color/colorText"
        android:text="Off"/>

</RelativeLayout>

> colors.xml which can be found from res > values > colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>

    <color name="colorOpen">#009900</color>
    <color name="colorClose">#ff0000</color>
    <color name="colorText">#ffffff</color>
</resources>

Here is the manifest, where we have to add the INTERNET permission

<uses-permission android:name="android.permission.INTERNET"/>

> AndroidManifest.xml 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.sodiarc.ledglower">
    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

> Here is our MainActivity.java

package com.sodiarc.ledglower;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity extends AppCompatActivity {
    String base_url = "http://sodiarcthings.com/iot/";
    String url = null;
    ProgressDialog pd;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        pd = new ProgressDialog(this);
        pd.setMessage("Loading");
        pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    }

    public void toggleLed(View v) {
        if(v.getId() == R.id.on) {
            url = base_url+"glowLed.php?state=1";
        } else if(v.getId() == R.id.off) {
            url = base_url+"glowLed.php?state=0";
        }
        new HitData().execute(url);
    }

    public class HitData extends AsyncTask<String,String,String> {
        @Override
        protected void onPreExecute() {
            pd.show();
        }

        @Override
        protected String doInBackground(String... urls) {
            String response = "";
            try {
                URL url = new URL(urls[0]);
                HttpURLConnection con = (HttpURLConnection) url.openConnection();
                con.setRequestMethod("GET");

                BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
                response = br.readLine();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return response;
        }

        @Override
        protected void onPostExecute(String res) {
            pd.cancel();
            Toast.makeText(getApplicationContext(), "Success", Toast.LENGTH_LONG).show();
        }
    }
}

Here is our final android app screenshot

Android Things Article Author

Author

Hi folks, I am co-founder and CEO at Sodiarc Technologies Pvt. Ltd. I am working on android for more than 5 years. I have skills, which includes Android, iOS, PHP and lot more. If you have any project related queries we can discuss it briefly, mail me at info@sodiarc.com

Android Things Article Author

Author

Hi folks, I am CTO at Sodiarc Technologies Pvt. Ltd. I am programming enthusiast. I have skills, which includes Android, iOS, PHP and lot more. If you have any project related queries we can discuss it briefly, mail me at info@sodiarc.com

Android Things Article Author

Author

Hi folks, I am a content writer and a blogger. Writing is my passion. A B.Tech graduate in Information Technology, who is still paving the way for achieving the goals of her life.


Website Security Test