HTTP Server/Client in Dart Language

Serves “A Basic HTTP Server” text response on http://127.0.0.1:2222

import 'dart:io';

main() {
  HttpServer
      .bind("127.0.0.1", 2222)
      .then((server) {
        server.listen((HttpRequest request) {
          request.response.write('A Basic HTTP Server');
          request.response.close();
        });
      });
}

Client

import 'dart:io';
import 'dart:convert';

main() {
new HttpClient().get('127.0.0.1', 2222, '/')
     .then((HttpClientRequest request) => request.close())
     .then((HttpClientResponse response) {
       response.transform(utf8.decoder).listen((contents) {
         print(contents);
       });
     });
}

Your first program in Dart Language

We are using chocolatey in Windows.

choco install dart-sdk

Reopen the cmd and install stagehand.

pub global activate stagehand

Let’s create our first program.

mkdir MyFirstApp
cd MyFirstApp

Creating a template…

stagehand console-full

Fetching dependencies…

pub get

Running app…

dart bin/main.dart

This example template also using a sample library within lib folder. You may change it’s content to affect calculate() function’s result. Such as…

int calculate() {
  return 10 * 2;
}

React-Native Notes Application (Dumb Example)

Here is a super dumb note taking application example which you can write a note and read all notes. Sure, you need nativebase installed in order to run this application.

Read Tab
Write Tab

notes.db

CREATE TABLE "notes" (
	"id"	INTEGER PRIMARY KEY AUTOINCREMENT,
	"title"	TEXT,
	"body"	TEXT,
	"author"	TEXT,
	"created"	TEXT
)

PHP Backend – Insert

<?php

$title = $_POST['title'];
$body = $_POST['body'];
$author = $_POST['author'];
$created = date('h:i:s d/m/Y');

$db = new SQLite3('notes.db');
$stmt = $db->prepare("INSERT INTO notes (title,body,author,created) VALUES (:title,:body,:author,:created)");
$stmt->bindValue(':title', $title, SQLITE3_TEXT);
$stmt->bindValue(':body',$body, SQLITE3_TEXT);
$stmt->bindValue(':author',$author, SQLITE3_TEXT);
$stmt->bindValue(':created',$created, SQLITE3_TEXT);
$stmt->execute();

PHP Backend – Read

<?php
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');

$db = new SQLite3('notes.db');
$results = $db->query('SELECT * FROM notes');
$json = array();

while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
   $json[] = $row;
}

echo json_encode($json);

App.js

import React from 'react';
import { FlatList } from 'react-native';
import { Container, Header, Card, CardItem, Text, Body, Icon,
Tabs, Tab, Form, Item, Input, Button, Right } from 'native-base';
export default class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = { dataSource: null, title: null, body: null, author: null}
    this.handleTitleChange = this.handleTitleChange.bind(this);
    this.handleBodyChange = this.handleBodyChange.bind(this);
    this.handleAuthorChange = this.handleAuthorChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }
  
  handleTitleChange(title) {
    this.setState({title: title});
  }
  handleBodyChange(body) {
    this.setState({body: body});
  }
  handleAuthorChange(author) {
    this.setState({author: author});
  }

  handleSubmit() {
    fetch('INSERT_BACKEND_URL', { 
    method: 'POST',
    mode: 'cors',
    cache: 'no-cache',
    headers: {
      'Content-Type' : 'application/x-www-form-urlencoded',
    },
    body: "title=" + this.state.title + "&body=" + this.state.body + "&author=" + this.state.author,
    });
  }
  componentDidMount() {
    setInterval(() => {
      return fetch('READ_BACKEND_URL')
        .then((response) => response.json())
        .then((responseJson) => {
          this.setState({
            dataSource: responseJson,
          }, function () {
          });
        })
        .catch((error) => {
          console.error(error);
        });
    }, 1000);
  }

  render() {
    return (
      <Container>
       <Header hasTabs />
       <Tabs>
        <Tab heading="Read">
      <FlatList
        data={this.state.dataSource}
        renderItem={({ item }) =>
          <Card>
            <CardItem header>
              <Text><Icon name="paper" /> {item.title}</Text>
            </CardItem>
            <CardItem>
              <Body>
                <Text>{item.body}</Text>
              </Body>
            </CardItem>
            <CardItem footer>
              <Text><Icon name="person" /> {item.author}</Text>
              <Right /><Text>{item.created}</Text>
            </CardItem>
          </Card>
        }
        keyExtractor={({ id }, index) => id}
      />
      </Tab>
      <Tab heading="Write">
      <Form onSubmit={this.handleSubmit}>
        <Item>
          <Input placeholder="title" onChangeText={this.handleTitleChange} />
        </Item>
        <Item>
          <Input placeholder="body" onChangeText={this.handleBodyChange} />
        </Item>
        <Item last>
          <Input placeholder="author" onChangeText={this.handleAuthorChange} />
        </Item>
          <Button onPress={this.handleSubmit}><Text>Save</Text></Button>
      </Form>
      </Tab>
      </Tabs>
      </Container>
    );

  }
}

JScript Refreshing Fetch Example

We can use setInterval function to refresh our fetched values automatically.

setInterval(function(){ }, 1000); // Runs our function repetitively every 1 seconds…

   componentDidMount() {
    setInterval(() => {
      return fetch('https://YOUR_API_URL')
        .then((response) => response.json())
        .then((responseJson) => {
          this.setState({
            dataSource: responseJson,
          }, function () {
          });
        })
        .catch((error) => {
          console.error(error);
        });
    }, 1000);
  }

Debian 10 Installing Nginx + PHP + PHP-FPM

Getting ready for running PHP in Debian 10 is just taking few steps. First of all check for updates with…

apt update -y

You may also run upgrade if you wish to upgrade packages…

apt upgrade -y

Now install nginx + php + php-fpm

apt install nginx php-fpm php -y

Edit /etc/nginx/sites-available/default and add index.php to the following line

index index.php index.html index.htm index.nginx-debian.html;

Also uncomment following lines, be careful to not uncomment second fastcgi_pass

  location ~ \.php$ {
                include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
                fastcgi_pass unix:/run/php/php7.3-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        }

You may restart nginx…

systemctl restart nginx

React-Native NativeBase Flatlist Example

In this example, i am showing how to fetch a json file and list it’s contents in Flatlist using NativeBase’s Card.

messages.json

{
  "title": "Messages List",
  "messages": [
    { "id": "1", "title": "My First Message", "body": "This is the first message.", "author": "author1" },
    { "id": "2", "title": "My Second Message", "body": "This is the second message", "author": "author1" }
  ]
}

App.js

import React from 'react';
import { ActivityIndicator, View, FlatList } from 'react-native';
import { Card, CardItem, Text, Body, Icon } from 'native-base';
export default class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = { isLoading: true, dataSource: null }
  }

  componentDidMount() {
    return fetch('https://dev.temelkuran.ist/messages.json')
      .then((response) => response.json())
      .then((responseJson) => {
        this.setState({
          isLoading: false,
          dataSource: responseJson.messages,
        }, function () {
        });
      })
      .catch((error) => {
        console.error(error);
      });
  }

  render() {

    if (this.state.isLoading) {
      return (
        <View style={{ flex: 1, padding: 20 }}>
          <ActivityIndicator />
        </View>
      )
    }

    return (
      <FlatList
        data={this.state.dataSource}
        renderItem={({ item }) =>
          <Card>
            <CardItem header>
              <Text><Icon name="paper" /> {item.title}</Text>
            </CardItem>
            <CardItem>
              <Body>
                <Text>{item.body}</Text>
              </Body>
            </CardItem>
            <CardItem footer>
              <Text><Icon name="person" /> {item.author}</Text>
            </CardItem>
          </Card>
        }
        keyExtractor={({ id }, index) => id}
      />
    );
  }
}

This application should look like:

Chart.JS PHP Embedded

Here is a silly example to use Chart.JS . However, we are using advantages of PHP. I personally do not recommend to use that way in production. Maybe the second way?

We have a database with 3 columns.

CREATE TABLE "data" (
	"id"	INTEGER PRIMARY KEY AUTOINCREMENT,
	"temperature"	INTEGER,
	"day"	INTEGER
)

Embedded PHP Code

<!DOCTYPE html>
<html>
<head>
<title>Chart.js PHP Example</title>
</head>

<body>
<canvas id="myChart" width="25" height="10"></canvas>

<?php
$db = new SQLite3('chart.db');
$result = $db->query('SELECT * FROM data');
?>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
    type: 'line',
    data: {
        labels: [
        <?php 
        while ($row = $result->fetchArray()) {
        echo "'";
        echo $row['day'];
        echo "',";
        } ?>
        ],
        datasets: [{
            label: 'Temperature',
            data: [
            <?php
            while($row = $result->fetchArray()) {    
            echo "'";
            echo $row['temperature'];
            echo "',";
            }
            ?>
                ],
            lineTension: 0.5,
            backgroundColor: 'transparent',
            borderColor: '#007bff',
            borderWidth: 4,
            pointBackgroundColor: '#007bff'        
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero: false
                }
            }]
        }
    }
});
</script>

</body>

</html> 

Second way. Smarter Maybe???

 <!DOCTYPE html>
<html>
<head>
<title>Chart.js PHP Example</title>
</head>

<body>
<canvas id="myChart" width="25" height="10"></canvas>

<?php
$db = new SQLite3('chart.db');
$result = $db->query('SELECT * FROM data');
?>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>

var labels1 = new Array();  
var data1 = new Array();
<?php while ($row = $result->fetchArray()) { ?>
labels1.push(<?php echo $row['day']; ?>);
data1.push(<?php echo $row['temperature']; ?>);
<?php } ?>

var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
    type: 'line',
    data: {
        labels: labels1,
        datasets: [{
            label: 'Temperature',
            data: data1,
            lineTension: 0.5,
            backgroundColor: 'transparent',
            borderColor: '#007bff',
            borderWidth: 4,
            pointBackgroundColor: '#007bff'        
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero: false
                }
            }]
        }
    }
});
</script>

</body>

</html> 

PHP SQLite3 User Login Example

Here is a simple PHP SQLite3 User Login example.

First create our database called Login.db in SQLite3.

CREATE TABLE "users" (
	"id"	INTEGER PRIMARY KEY AUTOINCREMENT,
	"username"	TEXT,
	"password"	TEXT
)

You will want to insert sample data in that database.

INSERT INTO "users" (username,password) VALUES ('test_username','test_password');

Let’s create our HTML form.

...
<form action="login.php" method="post">
Username:<input type="text" name="username"/><br/>
Password:<input type="password" name="password"/><br/>
<input type="submit"/>
</form>
...

Login.php

<?php

$username= $_POST['username'];
$password= $_POST['password'];

$db = new SQLite3('login.db');
$statement = $db->prepare('SELECT count(*) FROM users WHERE username=:username AND password=:password');
$statement->bindValue(':username', $username, SQLITE3_TEXT);
$statement->bindValue(':password', $password, SQLITE3_TEXT);
$result = $statement->execute();

while ($row= $result->fetchArray()) {
    $count = $row['count(*)'];
}

if ($count>0) {
   echo "Success!";
} 
else {
   echo "Failed to Login!";
}
 

React Recharts Chart Example with PHP Backend

First of all we need to create our database. I am choosing SQLite as always. We got 4 columns: id, temperature, humidity and day.

chart.db

CREATE TABLE "dataset" (
	"id"	INTEGER PRIMARY KEY AUTOINCREMENT,
	"temperature"	INTEGER,
	"humidity"	INTEGER,
	"day"	INTEGER
)

Here is our PHP backend.

json.php

<?php
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');

$db = new SQLite3('chart.db');
$results = $db->query('SELECT * FROM dataset');
$json = array();

while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
   $json[] = $row;
}

echo json_encode($json);

Do not forget to enable CORS with Allow-Origin: * just same as in example code.

Here is our React code.

App.js

import React from 'react';
import { LineChart, Line, CartesianGrid, XAxis, YAxis } from 'recharts';

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      error: null,
      isLoaded: false,
      data: [],
    }
  }

  componentDidMount() {
    fetch('http://localhost/json.php').then(res => res.json()).then((result) => {
      this.setState({ isLoaded: true, data: result });
    },
      (error) => {
        this.setState({ isLoaded: true, error });
      }
    );
  }

  render() {

    if (this.state.error) {
      return <div>Error: {this.state.error.message}</div>;
    } else if (!this.state.isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <LineChart width={600} height={300} data={this.state.data} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>
          <Line type="monotone" dataKey="temperature" stroke="#8884d8" />
          <Line type="monotone" dataKey="humidity" stroke="#8884d8" />
          <CartesianGrid stroke="#ccc" strokeDasharray="5 5" />
          <XAxis dataKey="year" />
          <YAxis />
        </LineChart>
      );
    }
  }
}

React Line Chart Example with Recharts

Simple line chart example in React with using Recharts.

After creating our project, please install Recharts.

npm install recharts 

json.php

<?php
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');

$string = 
'[{"year":"1881", "uv": 4000, "pv": 2400, "amt": 2400},
{"year":"1882", "uv": 3000, "pv": 1398, "amt": 2210},
{"year":"1883", "uv": 2000, "pv": 9800, "amt": 2290},
{"year":"1884", "uv": 2780, "pv": 3908, "amt": 2000},
{"year":"1885", "uv": 1890, "pv": 4800, "amt": 2181},
{"year":"1886", "uv": 2390, "pv": 3800, "amt": 2500},
{"year":"1887", "uv": 3490, "pv": 4300, "amt": 2100}]';

echo json_encode($string);

App.js

import React from 'react';
import { LineChart, Line, CartesianGrid, XAxis, YAxis } from 'recharts';

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      error: null,
      isLoaded: false,
      data: [],
    }
  }

  componentDidMount() {
    fetch('http://localhost/json.php').then(res => res.json()).then((result) => {
      this.setState({ isLoaded: true, data: JSON.parse(result) });
    },
      (error) => {
        this.setState({ isLoaded: true, error });
      }
    );
  }

  render() {

    if (this.state.error) {
      return <div>Error: {this.state.error.message}</div>;
    } else if (!this.state.isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <LineChart width={600} height={300} data={this.state.data} margin={{ top: 5, right: 20, bottom: 5, left: 0 }}>
          <Line type="monotone" dataKey="uv" stroke="#8884d8" />
          <CartesianGrid stroke="#ccc" strokeDasharray="5 5" />
          <XAxis dataKey="year" />
          <YAxis />
        </LineChart>
      );
    }
  }
}

React Fetch Example, A Single JSON Object

A simple example how to get a single JSON object in React with fetch.

import React from 'react';

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      error: null,
      isLoaded: false,
      data: [],
    }
  }

  componentDidMount() {
    fetch('http://ip.jsontest.com/').then(res => res.json()).then((result) => {
      this.setState({ isLoaded: true, data: JSON.stringify(result) });
    },
      (error) => {
        this.setState({ isLoaded: true, error });
      }
    );
  }

  render() {

    if (this.state.error) {
      return <div>Error: {this.state.error.message}</div>;
    } else if (!this.state.isLoaded) {
      return <div>Loading...</div>;
    } else {
      return this.state.data;
    }
  }
}

Result:

{"ip": "95.70.236.43"}

PHP, SQLite to JSON Array

Super simple example to get data from SQLite database and print as JSON array in PHP

<?php
header('Content-Type: application/json; charset=utf-8');

$db_name = "";   // your sqlite database

$db = new SQLite3($db_name);
$results = $db->query('SELECT * FROM `table_name`');
$json = array();

while ($row = $results->fetchArray(SQLITE3_ASSOC)) {
   $json[] = $row;
}

echo json_encode($json);

ESP32 + BME680

There is no such thing like ESP32 to make IoT applications easier.

BME680 is a low power gas, pressure, temperature & humidity sensor made by Bosch Sensortec.

Adafruit BME680
Adafruit Huzzah32

I am using Adafruit’s BME680 and Adafruit ESP32 Feather

We can use BME680 to measure indoor air parameters. I was thinking of making something with ESP, 2 years ago. So i decided to combine an ESP32 with BME680 together.

Here is an example code.

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include<WiFiClientSecure.h>
#include <WiFiMulti.h>

#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10

#define SEALEVELPRESSURE_HPA (1000)  // Sea level air pressure in your area

Adafruit_BME680 bme; // I2C

const char *uri = "API URI";  // https://api.temelkuran.ist
const char *host = "API ADDRESS";  // api.temelkuran.ist
const uint16_t port = 443; // HTTPS port

const char *RouterUsername = ""; // Your Router's Username
const char *RouterPassword = ""; // Your Router's Password

WiFiMulti WiFiMulti;

void setup()
{
    Serial.begin(115200);
  while (!Serial);
  Serial.println(F("BME680 async test"));

  if (!bme.begin()) {
    Serial.println(F("Could not find a valid BME680 sensor, check wiring!"));
    while (1);
  }
  
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150);

 WiFiMulti.addAP(RouterUsername, RouterPassword);
 Serial.println();
 Serial.println();
 Serial.print("WiFi Connecting...");
 
 while(WiFiMulti.run() != WL_CONNECTED) {
        Serial.print(".");
        delay(500);
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());

       delay(1000);
}

void loop()
{
  unsigned long endTime = bme.beginReading();
  if (endTime == 0) {
    Serial.println(F("Failed to begin reading :("));
    return;
  }
  Serial.print(F("Reading started at "));
  Serial.print(millis());
  Serial.print(F(" and will finish at "));
  Serial.println(endTime);

  Serial.println(F("You can do other work during BME680 measurement."));
  delay(50);

  if (!bme.endReading()) {
    Serial.println(F("Failed to complete reading :("));
    return;
  }
  Serial.print(F("Reading completed at "));
  Serial.println(millis());

  Serial.print(F("Temperature = "));
  Serial.print(bme.temperature);
  Serial.println(F(" *C"));

  Serial.print(F("Pressure = "));
  Serial.print(bme.pressure / 100.0);
  Serial.println(F(" hPa"));

  Serial.print(F("Humidity = "));
  Serial.print(bme.humidity);
  Serial.println(F(" %"));

  Serial.print(F("Gas = "));
  Serial.print(bme.gas_resistance / 1000.0);
  Serial.println(F(" KOhms"));

  Serial.print(F("Approx. Altitude = "));
  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(F(" m"));

  Serial.println();

   Serial.print("Connecting to ");
   Serial.println(host);

   WiFiClientSecure client;

   const char* root_ca = \
  "-----BEGIN CERTIFICATE-----\n" \
"MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\n" \
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \
"DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\n" \
"PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\n" \
"Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" \
"AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\n" \
"rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\n" \
"OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\n" \
"xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n" \
"7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\n" \
"aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n" \
"HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\n" \
"SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\n" \
"ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n" \
"AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\n" \
"R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\n" \
"JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\n" \
"Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n" \
"-----END CERTIFICATE-----\n";

   client.setCACert(root_ca); 
   
    if (!client.connect(host, port)) {
        Serial.println("Connection failed.");
        Serial.println("Waiting 5 seconds before retrying...");
        delay(5000);
        return;
    }
    
  String body = 
  "temperature=" + String(bme.temperature) +
  "&humidity=" + String(bme.humidity) +
  "&pressure=" + String(bme.pressure/100) +
  "&gas=" + String(bme.gas_resistance/1000) +
  "&altitude=" + String(bme.readAltitude(SEALEVELPRESSURE_HPA)); 

  String postRequest = 
  "POST " + uri + " HTTP/1.1\r\n" + 
  "Host: " + host + "\r\n" + 
  "Content-Type: application/x-www-form-urlencoded\r\n" +
  "Content-Length: " + body.length() + "\r\n" +
  "\r\n" + body;
  
  Serial.println(postRequest);
  client.print(postRequest);
  client.stop();

  Serial.println();
  Serial.println("***DONE***");
  Serial.println();
  delay(6000);
}

This example basically prints gathered values from BME680 and posts it to API every 6 seconds.

For those who gets Adafruit_Sensor.h not found error, you may download it from here.

Simple React-Native Form Example

Here, we are going to prepare a simple app which posts name and surname data to our php endpoint.

You may want to check Simple React Form Example to learn how to prepare a SQLite database which suits our needs.

Here our php endpoint Endpoint.php . We are using a SQLite database called my.db

<?php
header("Access-Control-Allow-Origin: *");

error_reporting(0);

$name = $_POST['name'];
$surname = $_POST['surname'];

if (!empty($name) && !empty($surname)) {
$db = new SQLite3('my.db');
$db->exec("INSERT INTO names VALUES ('$name','$surname')");
echo "done";
}
else {
echo "name or surname is empty";
}

Now React Native part. App.js

Note that it uses native-base components for UI. You may want to check my previous posts to learn how to install native-base.

import React, { Component } from 'react';
import { Container, Header, Content, Input, Item, Form, Button, Text } from 'native-base';

export default class App extends Component{
  constructor(props) {
    super(props);

    this.state = {name: '', surname: ''};
    this.handleNameChange = this.handleNameChange.bind(this);
    this.handleSurnameChange = this.handleSurnameChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleNameChange(name) {
    this.setState({name: name});
  }

  handleSurnameChange(surname) {
    this.setState({surname: surname});
  }

  handleSubmit() {    
      fetch('http://******IP_ADDRESS_HERE******/endpoint.php', { 
        method: 'POST',
        mode: 'cors',
        cache: 'no-cache',
        headers: {
          'Content-Type' : 'application/x-www-form-urlencoded',
        },
        body: "name=" + this.state.name + "&surname=" + this.state.surname,
        }).then((res)=> console.log(res)).catch((error) => console.error(error));
  }
  
  render() {
   return (
    <Container>
    <Header />
    <Content>
      <Form onSubmit={this.handleSubmit}>
        <Item>
          <Input placeholder="Name" onChangeText={this.handleNameChange} />
        </Item>
        <Item last>
          <Input placeholder="Surname" onChangeText={this.handleSurnameChange} />
        </Item>
          <Button onPress={this.handleSubmit}><Text>Save</Text></Button>
      </Form>
    </Content>
  </Container>
   );
 }
}

Change IP_ADDRESS_HERE with your target IP. Note that, it will not allow HTTP addresses in production release, so you need to set up HTTPS.

Simple React Form Example

This form will post ‘name and surname’ values to our PHP endpoint. It’s an ***extremely*** simple example which uses fetch to post data to our endpoint using get method.

Let’s start with our simple database.

First of all we need to create our SQLite database. I recommend to use https://sqlitebrowser.org/ Download it and create a database called my.db and table called names with two columns ; name and surname as text type. We will put our db near endpoint.php file where we serving our endpoint.

CREATE TABLE "names" (
	"name"   TEXT,
	"surname"   TEXT
);

Create our php endpoint as endpoint.php . It’s serving on 127.0.0.1 with EasyPHP. (Be sure that you put my.db near it)

<?php

error_reporting(0);

$name = $_GET['name'];
$surname = $_GET['surname'];

if (!empty($name) && !empty($surname)) {
$db = new SQLite3('my.db');
$db->exec("INSERT INTO names VALUES ('$name','$surname')");
echo "done";
}
else {
echo "name or surname is empty";
}

Finally, let’s create our React project somewhere else. Come in to CMD.

npx create-react-app your_app

Edit your_app/src/App.js file

import React from 'react';

export default class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {name: '', surname: ''};
    this.handleNameChange = this.handleNameChange.bind(this);
    this.handleSurnameChange = this.handleSurnameChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleNameChange(event) {
    this.setState({name: event.target.value});
  }
  handleSurnameChange(event) {
    this.setState({surname: event.target.value});
  }

  handleSubmit(event) {
    fetch('http://127.0.0.1/endpoint.php?name='+this.state.name+'&surname='+this.state.surname);
    alert('Done!');
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
      <label>
        Name:
        <input type="text" value={this.state.name} onChange={this.handleNameChange} />
      </label>
      <label>
        Surname:
        <input type="text" value={this.state.surname} onChange={this.handleSurnameChange} />
      </label>
      <input type="submit" value="Submit" />
    </form>
    );
  }
}

You can test this example with

npm start

Note: If you want to use POST method instead of GET method, you can change fetch like that.

 fetch('http://127.0.0.1/endpoint.php', { 
    method: 'POST',
    mode: 'cors',
    cache: 'no-cache',
    headers: {
      'Content-Type' : 'application/x-www-form-urlencoded',
    },
    body: "name=" + this.state.name + "&surname=" + this.state.surname,
    });

Body of POST Requests with HTTP/1.1

I recommend people to use the following structure of post requests minimally. Well, otherwise there is no way to do that thing.

POST /yis HTTP/1.1
Host: yismypeaple.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 30

name="neym"&surname="soerneym"

This example will post name=”neym” and surname=”soerneym” to yismypeaple.com/yis As you can see Content-Length is just total length of body which is starting with name=

You can get many information from there https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST

Post to HTTPS with ESP8266 / ESP32

The main difference between posting to http and https is using WiFiClientSecure instead of WiFiClient and using client.setCACert();

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <WiFiMulti.h>

WiFiMulti WiFiMulti;

const char *host = "my.api.com";
const char *uri = "/post_to_there";

void setup()
{
 Serial.begin(115200);
 WiFiMulti.addAP("Router_Username", "Router_Password");
 Serial.println();
 Serial.println();
 Serial.print("WiFi Connecting...");
 
 while(WiFiMulti.run() != WL_CONNECTED) {
        Serial.print(".");
        delay(500);
    }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

       delay(1000);
}

void loop()
{
   Serial.print("Connecting to ");
   Serial.println(host);

   WiFiClientSecure client;

   const char* root_ca = \
  "-----BEGIN CERTIFICATE-----\n" \
"MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\n" \
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \
"DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\n" \
"PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\n" \
"Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" \
"AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\n" \
"rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\n" \
"OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\n" \
"xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n" \
"7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\n" \
"aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\n" \
"HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\n" \
"SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\n" \
"ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\n" \
"AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\n" \
"R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\n" \
"JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\n" \
"Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n" \
"-----END CERTIFICATE-----\n";

   client.setCACert(root_ca); 
   
    if (!client.connect(host, port)) {
        Serial.println("Connection failed.");
        Serial.println("Waiting 5 seconds before retrying...");
        delay(5000);
        return;
    }
    
  String body = "BODY to be Posted";

  String postRequest = 
  "POST " + uri + " HTTP/1.1\r\n" + 
  "Host: " + host + "\r\n" + 
  "Content-Type: application/x-www-form-urlencoded\r\n" +
  "Content-Length: " + body.length() + "\r\n" +
  "\r\n" + body;
  
  Serial.println(postRequest);
  client.print(postRequest);
  client.stop();

  Serial.println();
  Serial.println("***DONE***");
  Serial.println();
  delay(6000);
}

We need our endpoint’s root certificate to establish communication with HTTPS pages. ‘root_ca’ variable is holding our endpoint’s root certificate. We need to know which certificate our endpoint is using. So we can gather it with different ways. Here…

You can find root certificate from your SSL providers website or just visiting the address.

You can find certificate key in exported file.

Adding Native-Base to your React Native App

Native-Base is an UI library to create your UIs much faster and simpler.

Create your app first.

react-native init MyApp

I recommend you to install Yarn.

npm install yarn

Go in your application’s main folder and install native-base.

npm install native-base --save

Now link native-base with your app.

react-native link

Let’s test our first app. Edit your App.js file like this.

import React from 'react';
import { Container, H1 } from 'native-base';

export default class App extends Component {
  render() {
    return (
      <Container>
          <H1>
            My first app with native-base.
          </H1>
      </Container>
    );
  }
}

Run your app.

react-native run-android

Preparing a release with React-Native for Android

In React-Native, debugging is relatively easy but preparing an app for Google Play Store or apk for your phone needs a key to sign your app.

Get in CMD as administrator. Go to the JDK directory. cd C:\Program Files\Java\jdk*****\bin
Type the following to create a file called my-upload-key.keystore in that folder. You can change the keystore name or alias. It will ask for password, i recommend you to type a strong one.

keytool -genkeypair -v -keystore my-upload-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000

Copy that keystore file to android/app folder in your application directory.

Edit android/gradle.properties and add the following.

MYAPP_UPLOAD_STORE_FILE=my-upload-key.keystore
MYAPP_UPLOAD_KEY_ALIAS=my-key-alias
MYAPP_UPLOAD_STORE_PASSWORD=YOUR_PASSWORD
MYAPP_UPLOAD_KEY_PASSWORD=YOUR_PASSWORD

Edit android/app/build.gradle, add the release {} part and change signingConfigs.debug as .release

android {
    ...
    defaultConfig { ... }
    signingConfigs {
        release {
            if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
                storeFile file(MYAPP_UPLOAD_STORE_FILE)
                storePassword MYAPP_UPLOAD_STORE_PASSWORD
                keyAlias MYAPP_UPLOAD_KEY_ALIAS
                keyPassword MYAPP_UPLOAD_KEY_PASSWORD
            }
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
}

cd in android folder and type

gradlew bundleRelease

AAB file is now ready in android/app/build/outputs/bundle/release/app.aab . You can submit to Google Play Store.

To test the release and create an apk file. Run app with following.

react-native run-android --variant=release

Your apk is ready in android\app\build\outputs\apk\release

Creating a React-Native Application

Before creating a React Native Application in Windows, i recommend to use Chocolatey. It’s a package manager application, just like yum, apt, dnf, portsnap in Linux and BSD. Install chocolatey as administrator with following CMD command.

Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

I recommend to install NodeJS (especially LTS), JDK and Python in case if we need to follow react-native command instead of Expo CLI.

choco install -y nodejs-lts python2 jdk8

Now we are ready to install react-native cli to create our sample project.

npm install -g react-native-cli

Now we need to install Android Studio. Get it from there: https://developer.android.com/studio

We need to set two environment variable. Go in to Control Panel. Choose System and Security -> Change Settings -> Advanced Tab -> Environment Variables and click New. Set a ANDROID_HOME variable with location C:\Users\<em>YOUR_USERNAME</em>\AppData\Local\Android\Sdk , secondly set a platform-tools variable with path C:\Users\<em>YOUR_USERNAME</em>\AppData\Local\Android\Sdk\platform-tools . Change YOUR_USERNAME with your Windows username.

Now it’s Android Studio part. We need to download couple things and create an emulator device. Open it., yes. Click Configure -> SDK Manager. Check Android 9.0 (Pie), then check Show Package Details and check Google APIs Intel x86 Atom System Image and Android SDK Platform 28 etc.

Now come to the SDK Tools path and download Android SDK Build Tools, version 28.0.3.

Click Apply.

Turn back to Android Studio intro menu.

Click Configure -> AVD Manager -> Create Virtual Device -> ? A device choice of yours i choose Pixel 2 -> Choose Pie as System Image.

If you did all of these things, let’s create our sample project.

react-native init MySampleProject

Come in with cd MySampleProject. Run it in debug mode.

react-native run-android

Probably you get an error while building… Finally, there is a tweak that you need to do in your created MySampleProject folder. Go in to android folder, edit build.gradle file then change to minSdkVersion =  28