React Native Simple Spy App

There are many types of Spy Gadgets in market. The App that we are going to discuss in this article can have many utilities, for example :

  1. It can be used to monitor number of times light of a room is switched on/off.
  2. If your child has an independent room you can find out if he is really having good sleep at night.
  3. It can also be used to check some ones sleep pattern because generally when someone wake up at night he turns on light.

So basically this app will give us information of how many times light of a room was turned on and off. Data will be collected by our device built with Arduino. We will use Light Dependent Resistor/Photo-resistor and Blue-tooth module (HC-05) to build our hardware. The Device will keep track of no of times light was turned on and keep transmitting it to the paired/connected devices. The App will be able to establish connection with device and request the count of times light was on.

We can created different health monitoring apps just by modifying some of the things in this app. For example we can use pulse sensor instead of LDR, collect data and view it in different graphical formats in the App.

Connections :

Blue-tooth module is connected same as our previous tutorial. One side of Photo-resistor is connected via 4.7K Ohm resistor to ground, another one is connected to 5v and A0 pin.

Below is the code for our device :

#include <SoftwareSerial.h>

SoftwareSerial BTserial(0, 1); // RX | TX

unsigned long countLightOn = 0; 
int flag = 0;
const int sensitivity = 500;

void setup() {
  // initialize serial communications (for debugging only):
  Serial.begin(9600);
}

void loop() {
  // read the sensor:
  int sensorReading = analogRead(A0);
  // print the sensor reading so you know its range
  if(sensorReading <= sensitivity){
      flag = 0;
  }
  if(flag == 0){
    if(sensorReading > sensitivity){
      countLightOn++;
      flag = 1;
    }
  }
  Serial.println(countLightOn);
  Serial.println(";");
  delay(3000);        // delay in between reads for stability
}

In the above code we are using SoftwareSerial library to transmit data. Pins 0 and 1 i.e. Rx and Tx are used for serial communicated between Arduino and  Bluetooth module. ‘Sensitivity’ constant determines how much light should give signal of light turned on.  A0 pin is used to read signal from Photo-resistor to Arduino. So when LDR signal is higher than its sensitivity then we  increase the light counter by one.

Below is the code for our React Native App :

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View,
  Button,
  FlatList,
  Switch,
  TouchableOpacity,
  ToastAndroid
} from 'react-native';
var _ = require('lodash');
import BluetoothSerial from 'react-native-bluetooth-serial'

export default class App extends Component<{}> {
  constructor (props) {
    super(props)
    this.state = {
      isEnabled: false,
      discovering: false,
      devices: [],
      unpairedDevices: [],
      connected: false,
      LightOnCount: 0
    }
  }
  componentWillMount(){

    Promise.all([
      BluetoothSerial.isEnabled(),
      BluetoothSerial.list()
    ])
    .then((values) => {
      const [ isEnabled, devices ] = values

      this.setState({ isEnabled, devices })
    })

    BluetoothSerial.on('bluetoothEnabled', () => {

      Promise.all([
        BluetoothSerial.isEnabled(),
        BluetoothSerial.list()
      ])
      .then((values) => {
        const [ isEnabled, devices ] = values
        this.setState({  devices })
      })

      BluetoothSerial.on('bluetoothDisabled', () => {

         this.setState({ devices: [] })

      })
      BluetoothSerial.on('error', (err) => console.log(`Error: ${err.message}`))

    })

  }
  connect (device) {
    this.setState({ connecting: true })
    BluetoothSerial.connect(device.id)
    .then((res) => {
      console.log(`Connected to device ${device.name}`);
      ToastAndroid.show(`Connected to device ${device.name}`, ToastAndroid.SHORT);
    })
    .catch((err) => console.log((err.message)))
  }
  _renderItem(item){

    return(<TouchableOpacity onPress={() => this.connect(item.item)}>
            <View style={styles.deviceNameWrap}>
              <Text style={styles.deviceName}>{ item.item.name ? item.item.name : item.item.id }</Text>
            </View>
          </TouchableOpacity>)
  }
  enable () {
    BluetoothSerial.enable()
    .then((res) => this.setState({ isEnabled: true }))
    .catch((err) => Toast.showShortBottom(err.message))
  }

  disable () {
    BluetoothSerial.disable()
    .then((res) => this.setState({ isEnabled: false }))
    .catch((err) => Toast.showShortBottom(err.message))
  }

  toggleBluetooth (value) {
    if (value === true) {
      this.enable()
    } else {
      this.disable()
    }
  }
  discoverAvailableDevices () {
    console.log("discovering");
    if (this.state.discovering) {
      return false
    } else {
      this.setState({ discovering: true })
      BluetoothSerial.discoverUnpairedDevices()
      .then((unpairedDevices) => {
        const uniqueDevices = _.uniqBy(unpairedDevices, 'id');
        console.log(uniqueDevices);
        this.setState({ unpairedDevices: uniqueDevices, discovering: false })
      })
      .catch((err) => console.log(err.message))
    }
  }
  toggleSwitch(){
    BluetoothSerial.write("T")
    .then((res) => {
      console.log(res);
      console.log('Successfuly wrote to device')
      this.setState({ connected: true })
    })
    .catch((err) => console.log(err.message))
  }
  readData(){
    BluetoothSerial.readFromDevice().
    then((res) => {
      const strArr = res.split(";");
      const LightOnCount = strArr[strArr.length - 2];
      const finalCount = LightOnCount.substring(0, LightOnCount.length - 1);
      this.setState({ LightOnCount: finalCount })
    })
    .catch((err) => console.log(err.message))
  }
  render() {

    return (
      <View style={styles.container}>
      <View style={styles.toolbar}>
            <Text style={styles.toolbarTitle}>Bluetooth Device List</Text>
            <View style={styles.toolbarButton}>
              <Switch
                value={this.state.isEnabled}
                onValueChange={(val) => this.toggleBluetooth(val)}
              />
            </View>
      </View>
        <Button
          onPress={this.discoverAvailableDevices.bind(this)}
          title="Scan for Devices"
          color="#841584"
        />
        <FlatList
          style={{flex:1}}
          data={this.state.devices}
          keyExtractor={item => item.id}
          renderItem={(item) => this._renderItem(item)}
        />
        <Text style={{alignSelf: "center", fontSize: 50, fontWeight: "bold", color: "#8B008B", marginBottom:50}} >{ this.state.LightOnCount }</Text>
        <Button
          onPress={this.readData.bind(this)}
          title="No of times light Switched On"
          color="#841584"
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#F5FCFF',
  },
  toolbar:{
    paddingTop:30,
    paddingBottom:30,
    flexDirection:'row'
  },
  toolbarButton:{
    width: 50,
    marginTop: 8,
  },
  toolbarTitle:{
    textAlign:'center',
    fontWeight:'bold',
    fontSize: 20,
    flex:1,
    marginTop:6
  },
  deviceName: {
    fontSize: 17,
    color: "black"
  },
  deviceNameWrap: {
    margin: 10,
    borderBottomWidth:1
  }
});

The above code is very similar to the code used in our previous tutorial. The new part is that when user taps “No of times light Switched On” button, data from our device is retrieved. The data is long string of data being transmitted since the time connection is established between Device and App. So, to get the latest count we are using delimiter and splitting string to get latest count.

Video Tutorial :