Elmin Delibašić
Published © GPL3+

Home Security System

Sony Spresense Board + NodeMCU + Google Firebase + Android Studio

ExpertFull instructions providedOver 4 days1,409

Things used in this project

Story

Read more

Custom parts and enclosures

Sound1.mp3

Sound2.mp3

Sound3.mp3

Schematics

Complete scheme (1)

Nonodemcu fuxcpkufjz

Complete scheme (2)

Shemaa mxxaolezkq

Code

test.ino

Arduino
void setup() {
    pinMode(LED0, OUTPUT);
    pinMode(LED1, OUTPUT);
    pinMode(LED2, OUTPUT);
    pinMode(LED3, OUTPUT);
}

void loop() {
    digitalWrite(LED0, HIGH);
    delay(100);
    digitalWrite(LED1, HIGH);
    delay(100);
    digitalWrite(LED2, HIGH);
    delay(100);
    digitalWrite(LED3, HIGH);
    delay(1000);

    digitalWrite(LED0, LOW);
    delay(100);
    digitalWrite(LED1, LOW);
    delay(100);
    digitalWrite(LED2, LOW);
    delay(100);
    digitalWrite(LED3, LOW);
    delay(1000);
}

sony_spresense_board.ino

Arduino
#include<SoftwareSerial.h>
#include <SDHCI.h>
#include <Audio.h>


int IN1 = 3, IN2 = 5, IN3 = 6, IN4 = 9, d = 10; //Stepper motor control
int pirPin = 13,micPin = 8, trigPin = 10, echoPin = 11, distance; //Sensor pin
int resPin = 2, LED = 12;



//Sound data
SDClass theSD;
AudioClass *theAudio;

File myFile;

bool ErrEnd = false;

static void audio_attention_cb(const ErrorAttentionParam *atprm)
{
  puts("Attention!");
  
  if (atprm->error_code >= AS_ATTENTION_CODE_WARNING)
    {
      ErrEnd = true;
   }
}

//end


void setup() {
  //Serial S Begin at 9600 Baud
  digitalWrite(resPin, HIGH);
  
  pinMode(resPin, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(trigPin, INPUT);
  pinMode(echoPin, INPUT);
  pinMode(LED, OUTPUT);
  }

void loop() {

  


    
    
  steppermotor();


  //PIR Sensor data -----------------------------------------------------------

  boolean pir_data = digitalRead(pirPin);
  if (pir_data == 1) {
    digitalWrite(LED, HIGH);
    audiosetup1();
    delay(5000);
    digitalWrite(resPin, LOW);   
    }
  else {

      digitalWrite(LED, LOW);
      
      }

  //HC-SR04 sensor data -------------------------------------------------------
  
    digitalWrite(trigPin, LOW); //turn off trigPin
    delayMicroseconds(2);   
    digitalWrite(trigPin, HIGH); //turn on trigPin
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW); //turn off trigPn
    long duration = pulseIn(echoPin, HIGH); //returns the sound wave travel time in microseconds
    int distance = duration*0.034/2; 
    
  if (distance < 7) {
  audiosetup2();
  delay(5000);
  digitalWrite(resPin, LOW);
  }

  //Microphone Module ---------------------------------------------------------

  
  boolean mic_data = digitalRead(micPin);

   if (mic_data == 1) {
  audiosetup3();
  delay(5000);
  digitalWrite(resPin, LOW);
  }
  

delay(500);
digitalWrite(resPin, LOW);

  
    
}




int steppermotor() {
  
  for (int i=0; i<150; i++) {
        digitalWrite(IN1, HIGH);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, HIGH);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, HIGH);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, HIGH);
     delay(d); 
                         }
for (int i=0; i<150; i++) {
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, HIGH);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, HIGH);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, HIGH);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, HIGH);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);  
                        }
  
  }

  int audiofile() {
    
    
  puts("loop!!");

  /* Send new frames to decode in a loop until file ends */
  int err = theAudio->writeFrames(AudioClass::Player0, myFile);

  /*  Tell when player file ends */
  if (err == AUDIOLIB_ECODE_FILEEND)
    {
      printf("Main player File End!\n");
    }

  /* Show error code from player and stop */
  if (err)
    {
      printf("Main player error code: %d\n", err);
      goto stop_player;
    }

  if (ErrEnd)
    {
      printf("Error End\n");
      goto stop_player;
    }

  /* This sleep is adjusted by the time to read the audio stream file.
     Please adjust in according with the processing contents
     being processed at the same time by Application.
  */

  usleep(3000);




stop_player:
  sleep(1);
  theAudio->stopPlayer(AudioClass::Player0);
  myFile.close();
  exit(1);
    
    }


void audiosetup1() {
  
  // start audio system
  theAudio = AudioClass::getInstance();

  theAudio->begin(audio_attention_cb);

  puts("initialization Audio Library");

  /* Set clock mode to normal */
  theAudio->setRenderingClockMode(AS_CLKMODE_NORMAL);

  theAudio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT);


  err_t err = theAudio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/sd0/BIN", AS_SAMPLINGRATE_AUTO, AS_CHANNEL_STEREO);

  /* Verify player initialize */
  if (err != AUDIOLIB_ECODE_OK)
    {
      printf("Player0 initialize error\n");
      exit(1);
    }

  /* Open file placed on SD card */
  myFile = theSD.open("Sound1.mp3");

  /* Verify file open */
  if (!myFile)
    {
      printf("File open error\n");
      exit(1);
    }
  printf("Open! %d\n",myFile);

  /* Send first frames to be decoded */
  err = theAudio->writeFrames(AudioClass::Player0, myFile);

  if ((err != AUDIOLIB_ECODE_OK) && (err != AUDIOLIB_ECODE_FILEEND))
    {
      printf("File Read Error! =%d\n",err);
      myFile.close();
      exit(1);
    }

  puts("Play!");

  /* Main volume set to -16.0 dB */
  theAudio->setVolume(-160);
  theAudio->startPlayer(AudioClass::Player0); 
  
  }

  void audiosetup2() {
  
  // start audio system
  theAudio = AudioClass::getInstance();

  theAudio->begin(audio_attention_cb);

  puts("initialization Audio Library");

  /* Set clock mode to normal */
  theAudio->setRenderingClockMode(AS_CLKMODE_NORMAL);

  theAudio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT);


  err_t err = theAudio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/sd0/BIN", AS_SAMPLINGRATE_AUTO, AS_CHANNEL_STEREO);

  /* Verify player initialize */
  if (err != AUDIOLIB_ECODE_OK)
    {
      printf("Player0 initialize error\n");
      exit(1);
    }

  /* Open file placed on SD card */
  myFile = theSD.open("Sound2.mp3");

  /* Verify file open */
  if (!myFile)
    {
      printf("File open error\n");
      exit(1);
    }
  printf("Open! %d\n",myFile);

  /* Send first frames to be decoded */
  err = theAudio->writeFrames(AudioClass::Player0, myFile);

  if ((err != AUDIOLIB_ECODE_OK) && (err != AUDIOLIB_ECODE_FILEEND))
    {
      printf("File Read Error! =%d\n",err);
      myFile.close();
      exit(1);
    }

  puts("Play!");

  /* Main volume set to -16.0 dB */
  theAudio->setVolume(-160);
  theAudio->startPlayer(AudioClass::Player0); 
  
  }

  void audiosetup3() {
  
  // start audio system
  theAudio = AudioClass::getInstance();

  theAudio->begin(audio_attention_cb);

  puts("initialization Audio Library");

  /* Set clock mode to normal */
  theAudio->setRenderingClockMode(AS_CLKMODE_NORMAL);

  theAudio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT);


  err_t err = theAudio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/sd0/BIN", AS_SAMPLINGRATE_AUTO, AS_CHANNEL_STEREO);

  /* Verify player initialize */
  if (err != AUDIOLIB_ECODE_OK)
    {
      printf("Player0 initialize error\n");
      exit(1);
    }

  /* Open file placed on SD card */
  myFile = theSD.open("Sound3.mp3");

  /* Verify file open */
  if (!myFile)
    {
      printf("File open error\n");
      exit(1);
    }
  printf("Open! %d\n",myFile);

  /* Send first frames to be decoded */
  err = theAudio->writeFrames(AudioClass::Player0, myFile);

  if ((err != AUDIOLIB_ECODE_OK) && (err != AUDIOLIB_ECODE_FILEEND))
    {
      printf("File Read Error! =%d\n",err);
      myFile.close();
      exit(1);
    }

  puts("Play!");

  /* Main volume set to -16.0 dB */
  theAudio->setVolume(-160);
  theAudio->startPlayer(AudioClass::Player0); 
  
  }

activity_main.xml

XML
Android Studio
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:background="#f2f2f2"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:gravity="center">

        <ImageView
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:src="@drawable/camera"/>

    </RelativeLayout>
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="260dp"
        android:layout_marginTop="270dp">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="#c2d1f0"
            android:alpha="0.6"></RelativeLayout>

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="80dp">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:textSize="20dp"
            android:text="Motion detect:"
            android:textColor="#404040"
            android:layout_marginLeft="10dp"/>
        <TextView
            android:id="@+id/text_pirdata"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginRight="50dp"
            android:layout_marginLeft="50dp"
            android:layout_marginTop="25dp"
            android:gravity="center"
            android:textStyle="bold"
            android:textColor="#000000"
            android:textSize="20dp"
            android:text="N/A"
            />
</RelativeLayout>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_marginTop="80dp"
            android:background="#7094db"
            android:alpha="0.5"></RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_marginTop="80dp">
        <TextView
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:textSize="20dp"
            android:text="Distance detect:"
            android:textColor="#404040"
            android:layout_marginLeft="10dp"/>
        <TextView
            android:id="@+id/text_ultrasonic"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_marginRight="50dp"
            android:layout_marginLeft="50dp"
            android:layout_marginTop="25dp"
            android:gravity="center"
            android:textSize="20dp"
            android:textStyle="bold"
            android:textColor="#000000"
            android:text="N/A"
            /> </RelativeLayout>

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:background="#3366cc"
            android:layout_marginTop="160dp"
            android:alpha="0.5"></RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="80dp"
            android:layout_marginTop="160dp">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="80dp"
                android:textSize="20dp"
                android:text="Speech detect:"
                android:textColor="#404040"
                android:layout_marginLeft="10dp"/>
            <TextView
                android:id="@+id/text_mic"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_marginRight="50dp"
                android:layout_marginLeft="50dp"
                android:layout_marginTop="25dp"
                android:gravity="center"
                android:textSize="20dp"
                android:textStyle="bold"
                android:textColor="#000000"
                android:text="N/A"
                /> </RelativeLayout>



    </RelativeLayout>

</RelativeLayout>

MainActivity.java

Java
Android Studio
package com.example.elmin.homesecuritysystem;

import android.graphics.Color;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

public class MainActivity extends AppCompatActivity {

    DatabaseReference dref;
    TextView text_pir, text_distance, text_mic;
    String dist, mic, pir;
    int col = Color.parseColor("#b32d00");



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


        text_pir = (TextView) findViewById(R.id.text_pirdata);
        text_distance = (TextView)findViewById(R.id.text_ultrasonic);
        text_mic = (TextView) findViewById(R.id.text_mic);


        dref = FirebaseDatabase.getInstance().getReference();
        dref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                 pir = dataSnapshot.child("pir_data").getValue().toString();
                 int pir_int = Integer.parseInt(pir);

                if (pir_int == 0){
                    text_pir.setText("No motion detected.");}
                    else {
                    text_pir.setText("Movement outside!");
                    text_pir.setTextColor(col);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        dref = FirebaseDatabase.getInstance().getReference();
        dref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                dist =  dataSnapshot.child("distance").getValue().toString();
                int dist_data = Integer.parseInt(dist);

                if (dist_data == 0){
                    text_distance.setText("Nothing detected.");}
                else {
                    text_distance.setText(dist +" meters away from entry!");
                    text_distance.setTextColor(col);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });


        dref = FirebaseDatabase.getInstance().getReference();
        dref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

               mic = dataSnapshot.child("mic").getValue().toString();
               int mic_data = Integer.parseInt(mic);

                if (mic_data == 0){
                    text_mic.setText("There is no one outside.");}
                else {
                    text_mic.setText("Conversation outside detected!");
                    text_mic.setTextColor(col);
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });



    }
}

sony_android.ino

Arduino
#include<SoftwareSerial.h>
#include <SDHCI.h>
#include <Audio.h>

SoftwareSerial nodemcu(0, 1); // 0 -> Tx (nodemcu), 1 -> Rx (nodemcu)

int IN1 = 3, IN2 = 5, IN3 = 6, IN4 = 9, d = 10; //Stepper motor control
int trigPin = 10, echoPin = 11, distance; //Sensor pin
int resPin = 2;



//Sound data
SDClass theSD;
AudioClass *theAudio;

File myFile;

bool ErrEnd = false;

static void audio_attention_cb(const ErrorAttentionParam *atprm)
{
  puts("Attention!");
  
  if (atprm->error_code >= AS_ATTENTION_CODE_WARNING)
    {
      ErrEnd = true;
   }
}

//end


void setup() {
  //Serial S Begin at 9600 Baud
  digitalWrite(resPin, HIGH);
  
  nodemcu.begin(9600);
  pinMode(resPin, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(trigPin, INPUT);
  pinMode(echoPin, INPUT);
  }

void loop() {

  


    
    
  steppermotor();
  
    digitalWrite(trigPin, LOW); //turn off trigPin
    delayMicroseconds(2);   
    digitalWrite(trigPin, HIGH); //turn on trigPin
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW); //turn off trigPn
    long duration = pulseIn(echoPin, HIGH); //returns the sound wave travel time in microseconds
    int distance = duration*0.034/2; 
    nodemcu.write(distance);
    
  if (distance < 7) {
  audiosetup();
  delay(5000);
  digitalWrite(resPin, LOW);
  }
  

  
  delay(500);
  digitalWrite(resPin, LOW);
  
    
}




int steppermotor() {
  
  for (int i=0; i<150; i++) {
        digitalWrite(IN1, HIGH);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, HIGH);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, HIGH);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, HIGH);
     delay(d); 
                         }
for (int i=0; i<150; i++) {
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, HIGH);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, HIGH);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, LOW);
        digitalWrite(IN2, HIGH);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);
        digitalWrite(IN1, HIGH);
        digitalWrite(IN2, LOW);
        digitalWrite(IN3, LOW);
        digitalWrite(IN4, LOW);
     delay(d);  
                        }
  
  }

  int audiofile() {
    
    
  puts("loop!!");

  /* Send new frames to decode in a loop until file ends */
  int err = theAudio->writeFrames(AudioClass::Player0, myFile);

  /*  Tell when player file ends */
  if (err == AUDIOLIB_ECODE_FILEEND)
    {
      printf("Main player File End!\n");
    }

  /* Show error code from player and stop */
  if (err)
    {
      printf("Main player error code: %d\n", err);
      goto stop_player;
    }

  if (ErrEnd)
    {
      printf("Error End\n");
      goto stop_player;
    }

  /* This sleep is adjusted by the time to read the audio stream file.
     Please adjust in according with the processing contents
     being processed at the same time by Application.
  */

  usleep(3000);




stop_player:
  sleep(1);
  theAudio->stopPlayer(AudioClass::Player0);
  myFile.close();
  exit(1);
    
    }


void audiosetup() {
  
  // start audio system
  theAudio = AudioClass::getInstance();

  theAudio->begin(audio_attention_cb);

  puts("initialization Audio Library");

  /* Set clock mode to normal */
  theAudio->setRenderingClockMode(AS_CLKMODE_NORMAL);

  theAudio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT);


  err_t err = theAudio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/sd0/BIN", AS_SAMPLINGRATE_AUTO, AS_CHANNEL_STEREO);

  /* Verify player initialize */
  if (err != AUDIOLIB_ECODE_OK)
    {
      printf("Player0 initialize error\n");
      exit(1);
    }

  /* Open file placed on SD card */
  myFile = theSD.open("Sound2.mp3");

  /* Verify file open */
  if (!myFile)
    {
      printf("File open error\n");
      exit(1);
    }
  printf("Open! %d\n",myFile);

  /* Send first frames to be decoded */
  err = theAudio->writeFrames(AudioClass::Player0, myFile);

  if ((err != AUDIOLIB_ECODE_OK) && (err != AUDIOLIB_ECODE_FILEEND))
    {
      printf("File Read Error! =%d\n",err);
      myFile.close();
      exit(1);
    }

  puts("Play!");

  /* Main volume set to -16.0 dB */
  theAudio->setVolume(-160);
  theAudio->startPlayer(AudioClass::Player0); 
  
  }

  

nodemcu_android.ino

Arduino
#include <PubSubClient.h>
#include <FirebaseArduino.h>
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>

#define FIREBASE_HOST "firebase_link"
#define FIREBASE_AUTH "firebase_secret_code"

#define WIFI_SSID "wifi_name"
#define WIFI_PASSWORD "wifi_password"

int pirPin = 5, micPin = 4, LED = 0;

void setup() {
  //Serial Begin at 9600 Baud 
  pinMode(pirPin, INPUT);
  pinMode(micPin, INPUT);
  pinMode(LED, OUTPUT);
  
  Serial.begin(9600);
     WiFi.begin (WIFI_SSID, WIFI_PASSWORD);
        while (WiFi.status() != WL_CONNECTED) {
           delay(500);
            Serial.print(".");
  
         }
          Serial.println ("");
          Serial.println ("WiFi Connected!");
          Serial.println(WiFi.localIP());
     Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);


  
}

void loop() {
    //PIR sensor data
    boolean pir_data = digitalRead(pirPin);
    Firebase.setInt("pir_data", pir_data);

    if (pir_data == 0) {
      digitalWrite(LED,LOW);
      }
    else {
      digitalWrite(LED, HIGH);
      }

    //Ultrasonic data
    int distance = Serial.read();
    Firebase.setInt("distance", distance);

    //Mic data from Sony Spresense
    boolean mic = digitalRead(micPin);
    Firebase.setInt("mic", mic);

    delay(1000);
  
}

Credits

Elmin Delibašić

Elmin Delibašić

4 projects • 24 followers
Elmin Delibašić - Electrical Engineering Student (Department of Telecomunications)

Comments