O plugin possui diversos componentes, e entenda por componentes as partes que formam este, como funções e serviços.
O código abaixo, declara os componentes do plugin.
// Cria as tabelas quando o plugin for ativado
register_activation_hook( __FILE__, 'criar_tabelas' );
function criar_tabelas() {
global $wpdb;
// Cria a tabela geiser_leitores
$table_name1 = $wpdb->prefix . 'geiser_leitores';
$charset_collate = $wpdb->get_charset_collate();
$sql1 = "CREATE TABLE $table_name1 (
id mediumint(9) NOT NULL AUTO_INCREMENT,
nome varchar(50) NOT NULL,
token varchar(50) NOT NULL,
status TINYINT(1) UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (id)
) $charset_collate;";
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql1 );
// Cria a tabela geiser_logs
$table_name2 = $wpdb->prefix . 'geiser_logs';
$sql2 = "CREATE TABLE $table_name2 (
id mediumint(9) NOT NULL AUTO_INCREMENT,
token varchar(50) NOT NULL,
lastdt datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
usvh float NOT NULL,
temp float NOT NULL,
hum float NOT NULL,
PRIMARY KEY (id)
) $charset_collate;";
dbDelta( $sql2 );
}
...
// Adiciona o menu no painel de administração
add_action( 'admin_menu', 'geiser_admin_menu' );
function geiser_admin_menu() {
add_menu_page( 'Geiser Admin', 'Geiser Admin', 'manage_options', 'geiser-admin', 'geiser_admin_page', 'geiser_admin_page' );
add_submenu_page( 'geiser-admin', 'Dispositivos', 'Dispositivos', 'manage_options', 'geiser_dispositivos_page', 'geiser_dispositivos_page' );
add_submenu_page( 'geiser-admin', 'Logs', 'Logs', 'manage_options', 'geiser_logs_page', 'geiser_logs_page' );
add_submenu_page( 'geiser-admin', 'Análise', 'Análise', 'manage_options', 'geiser_analise_page', 'geiser_analise_page' );
// Adiciona Chart.js ao painel de administração
add_action('admin_enqueue_scripts', function () {
wp_enqueue_script('chartjs', 'https://cdn.jsdelivr.net/npm/chart.js');
});
}
add_action('rest_api_init', 'registrar_rota_personalizada');
A função register_activation_hook chama uma função no momento da sua ativação. Que é feito apenas uma vez.
A função criar_tabelas , cria as tabelas no banco de dados MYSQL, que é o banco de dados do wordpress.
A função add_action permite registrar um menu no wordpress, conforme apresentamos abaixo, e a função add_menu_page, registra os itens do menu.
Cada chamada do add_menu_page, chama uma função que é referenciada, e ao clicar no menu é chamado.
add_submenu_page( 'geiser-admin', 'Análise', 'Análise', 'manage_options', 'geiser_analise_page', 'geiser_analise_page' );
function geiser_analise_page() {
global $wpdb;
$table_name = $wpdb->prefix . 'geiser_logs';
// Obtenha os dados do banco de dados
$logs = $wpdb->get_results("SELECT token, TIMESTAMP(lastdt) as datetime, AVG(usvh) as avg_usvh, AVG(temp) as avg_temp, AVG(hum) as avg_hum FROM $table_name GROUP BY token, UNIX_TIMESTAMP(lastdt) DIV (15 * 60) ORDER BY token, datetime", ARRAY_A);
// Iniciar a saída do HTML
ob_start();
?>
<div class="wrap">
<h1>Geiser Análise</h1>
<div>
<canvas id="geiserChart"></canvas>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Organiza os dados para o gráfico
var logs = <?php echo json_encode($logs); ?>;
var tokens = [];
var data = {
usvh: {},
temp: {},
hum: {}
};
logs.forEach(function (log) {
if (!data.usvh.hasOwnProperty(log.token)) {
data.usvh[log.token] = [];
data.temp[log.token] = [];
data.hum[log.token] = [];
}
data.usvh[log.token].push({x: log.datetime, y: parseFloat(log.avg_usvh)});
data.temp[log.token].push({x: log.datetime, y: parseFloat(log.avg_temp)});
data.hum[log.token].push({x: log.datetime, y: parseFloat(log.avg_hum)});
});
Object.keys(data.usvh).forEach(function (key) {
tokens.push({
label: 'Token ' + key + ' - usvh',
data: data.usvh[key],
fill: false,
borderColor: 'rgb(75, 192, 192)',
tension: 0.1
});
tokens.push({
label: 'Token ' + key + ' - temp',
data: data.temp[key],
fill: false,
borderColor: 'rgb(255, 99, 132)',
tension: 0.1
});
tokens.push({
label: 'Token ' + key + ' - hum',
data: data.hum[key],
fill: false,
borderColor: 'rgb(255, 205, 86)',
tension: 0.1
});
});
// Cria o gráfico
var ctx = document.getElementById('geiserChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
datasets: tokens
},
options: {
scales: {
x: {
type: 'time',
time: {
unit: 'minute',
displayFormats: {
minute: 'HH:mm'
}
}
}
}
}
});
});
</script>
</div>
<?php
// Encerrar a saída do HTML
echo ob_get_clean();
}
Criando um Web Service
O Web Service é um serviço web que permite através dos verbos HTTP, armazenar , visualizar e gerenciar dados.
Incluiremos um web service, através do comando .
// Adiciona a rota do web service para chamar o arquivo ./ws/registra_log.php
add_action( 'rest_api_init', 'geiser_register_api_routes' );
...
function geiser_register_api_routes() {
//...
register_rest_route( 'geiser/v1', '/registra_log', array(
'methods' => 'GET',
'callback' => 'geiser_registra_log_endpoint',
'permission_callback' => function () {
return current_user_can( 'manage_options' );
}
) );
}
// Endpoint do web service para inserir dados na tabela geiser_logs
function geiser_logs_endpoint( WP_REST_Request $request ) {
global $wpdb;
$json = $request->get_json_params();
// Insere os dados na tabela geiser_logs
$table_name = $wpdb->prefix . 'geiser_logs';
$data = array(
'id_leitor' => $json['id_leitor'],
'nome' => $json['nome'],
'ip' => $json['ip'],
'lastdt' => $json['lastdt'],
'status' => $json['status']
);
$wpdb->insert( $table_name, $data );
return 'Dados inseridos na tabela com sucesso.';
}
Perceba que incluiremos o add_action, depois referenciamos a função geiser_register_api_routes, que registra o rest, através da chamada register_rest_route.
Que ao ser chamado, chama a função geiser_logs_endpoint.
Como chamar no arduino
O Arduino armazena o envia os dados para o web service, através do fonte: GIESER\hardware\MSTemp02
Do mesmo projeto, acima mencionado, para economizarmos tempo, irei apresentar o fragmento do código:
Utilizaremos um ethernet shield, para mostrar os dados, e para isso, incluiremos a biblioteca Ethernet.h, conforme apresentado no site.
Iremos definir a porta PORT e o endereço do URL, do wordpress, conforme apresentado no url.
E por fim chamaremos no loop a função WriteSite, que passa os dados que se deseja para o site, conforme apresentado.
#include <Ethernet.h>
#define PORT 80
#define url "http://177.26.228.0/wp-json/Geiser/v1/registro.php"
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// Set the static IP address to use if the DHCP fails to assign
IPAddress ip(192, 168, 0, 177);
IPAddress myDns(192, 168, 0, 1);
// Initialize the Ethernet client library
// with the IP address and port of the URL
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
void WriteSite()
{
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.print("connecting to ");
Serial.print(url);
Serial.println("...");
// if you get a connection, report back via serial:
if (client.connect(url, PORT)) {
Serial.print("connected to ");
Serial.println(client.remoteIP());
// Make a HTTP POST request:
client.println("POST /your_endpoint_here HTTP/1.1");
client.print("Host: ");
client.println(url);
client.println("Content-Type: application/json");
client.print("usvh: ");
client.println(usvh);
client.print("temp: ");
client.println(temperature);
client.print("hum: ");
client.println(humidity);
client.println("Connection: close");
// Calculate the content length
String jsonBody = String("{\"usvh\":") + String(usvh) + String(",\"temp\":") + String(temperature) + String(",\"hum\":") + String(humidity) + String("}");
client.print("Content-Length: ");
client.println(jsonBody.length());
client.println(); // Required empty line before the body
client.print(jsonBody);
client.println();
} else {
// if you didn't get a connection to the server:
Serial.println("connection failed");
}
beginMicros = micros();
}
o client é uma variavel de objeto, que armazena a conexão realizada com o servidor, nele chamaremos um cabeçalho do protocolo http, incluindo no verbo http POST as informações que desejamos incluir.
Desta forma simples conseguimos enviar dados para um servidor web.