This code example has been tested and improved to be executed in Meshlium with the data coming from a Wireless Sensor Network created with Waspmote.
This example will read, from Meshlium's Xbee module, frames from Waspmote with acceloremter sensor data. Valid frames will be stored on a database.
For this example the frame will have this structure:
<mote_id>#ACCX#Sensor_value#ACCY#Sensor_value#ACCZ#Sensor_value
A valid frame can be:
W01#ACCX#1#ACCY#1#ACCZ#1026
Waspmote will initialize components, read accelerometer sensor values and send it to meshlium using it's Xbee 802.15.4.
File:
"Xbee_accelerometer_humidity.pde"
Note:
Meshlium Xbee MAC is hardcoded into code. Update with your Xbee MAC.
/*
* ------Waspmote XBee 802.15.4 Sending & Receiving Example------
*
* Explanation: This example shows how to send and receive packets
* using Waspmote XBee 802.15.4 API
*
* This code sends a packet to another node and waits for an answer from
* it. When the answer is received it is shown.
*
* Copyright (C) 2009 Libelium Comunicaciones Distribuidas S.L.
* http://www.libelium.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Version: 0.1
* Design: David Gascón
* Implementation: Alberto Bielsa
*/
packetXBee* paq_sent;
int8_t state=0;
long previous=0;
int g=0;
int i=0;
char X[10];
float value=0;
char data[100];
#define SENS_PIR SENS_SOCKET7
void setup()
{
// Inits the XBee 802.15.4 library
xbee802.init(XBEE_802_15_4,FREQ2_4G,NORMAL);
// Powers XBee
xbee802.ON();
ACC.begin(); // opens I2C bus
ACC.setMode(ACC_ON); // starts accelerometer
}
void loop()
{
sendData();
delay(1000);
}
// sends a message changing it depending on the input option
void sendData()
{
paq_sent=(packetXBee*) calloc(1,sizeof(packetXBee));
paq_sent->mode=UNICAST;
paq_sent->MY_known=0;
paq_sent->packetID=0x52;
paq_sent->opt=0;
xbee802.hops=0;
xbee802.setOriginParams(paq_sent, "SENDER", NI_TYPE);
sprintf(data,"W01#ACCX#%d#ACCY#%d#ACCZ#%d%c%c",ACC.getX(), ACC.getY(), ACC.getZ(), '\r', '\n');
xbee802.setDestinationParams(paq_sent, "0013A20040312A9F", data, MAC_TYPE, DATA_ABSOLUTE);
state=xbee802.sendXBee(paq_sent);
if(!state)
{
XBee.println("OK");
}
free(paq_sent);
paq_sent=NULL;
}
The database to store data will store the following values: ID of the mote, sensor value recived, and the time of the received frame will be stored.
First we need to create the database for the example.
CREATE SCHEMA IF NOT EXISTS `cursoWasp` DEFAULT CHARACTER SET utf8 ; USE `cursoWasp`; GRANT ALL PRIVILEGES ON cursoWasp.* TO 'cursoUser'@'localhost' IDENTIFIED BY 'cursoPass' WITH GRANT OPTION; flush privileges; DROP TABLE IF EXISTS `mote_data`; CREATE TABLE IF NOT EXISTS `mote_data` ( `id` int(10) unsigned NOT NULL auto_increment, `date` datetime NOT NULL, `mote_id` varchar(100) NOT NULL, `s1_id` varchar(100) NOT NULL, `s1_val` varchar(100) NOT NULL, `s2_id` varchar(100) NOT NULL, `s2_val` varchar(100) NOT NULL, `s3_id` varchar(100) NOT NULL, `s3_val` varchar(100) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
This program reads frames received through XBee module and store it on a MySQL database.
File:
"sniffer_ddbb.c"
Compilation on Meshlium:
gcc -o sniffer_ddbb -I/usr/include/mysql sniffer_ddbb.c -L/usr/lib/mysql -lmysqlclient -Wall
Usage:
sniffer_ddbb S0 localhost
Note:
This code works at 19200 bauds, you can change it on code. Just look for string B19200 and replace 19200 with the speed you need.
/*
* Copyright (C) 2008 Libelium Comunicaciones Distribuidas S.L.
* http://www.libelium.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Version 0.1
* Author: Octavio Benedi Sanchez
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <termios.h> /* Terminal control library (POSIX) */
#include <ctype.h>
#include <mysql.h>
#define MAX 500
#define MAX_SQL 700
int main(int argc, char *argv[]) {
int sd = 3;
char *serialPort = "";
char *serialPort0 = "/dev/ttyS0";
char *serialPort1 = "/dev/ttyS1";
char *USBserialPort0 = "/dev/ttyUSB0";
char *USBserialPort1 = "/dev/ttyUSB1";
char valor[MAX] = "";
char c;
struct termios opciones;
char *s0 = "S0";
char *s1 = "S1";
char *u0 = "USB0";
char *u1 = "USB1";
/**************************************
* Defines para crear la insercion SQL
*************************************/
char sql[MAX_SQL] = "";
MYSQL mysql;
/* STARTING MAIN */
if (argc != 3) {
fprintf(stderr, "Usage: %s port bbdd_ip\n", argv[0]);
exit(0);
}
if (!strcmp(argv[1], s0)) {
serialPort = serialPort0;
}
if (!strcmp(argv[1], s1)) {
serialPort = serialPort1;
}
if (!strcmp(argv[1], u0)) {
serialPort = USBserialPort0;
}
if (!strcmp(argv[1], u1)) {
serialPort = USBserialPort1;
}
if (!strcmp(serialPort, "")) {
fprintf(stderr, "Choose a valid port (S0, S1, USB0, USB1)\n");
exit(0);
}
if ((sd = open(serialPort, O_RDWR | O_NOCTTY | O_NDELAY)) == -1) {
fprintf(stderr, "Unable to open the serial port %s - \n", serialPort);
exit(-1);
} else {
if (!sd) {
sd = open(serialPort, O_RDWR | O_NOCTTY | O_NDELAY);
}
fcntl(sd, F_SETFL, 0);
}
tcgetattr(sd, &opciones);
cfsetispeed(&opciones, B38400);
cfsetospeed(&opciones, B38400);
opciones.c_cflag |= (CLOCAL | CREAD);
/*No parity*/
opciones.c_cflag &= ~PARENB;
opciones.c_cflag &= ~CSTOPB;
opciones.c_cflag &= ~CSIZE;
opciones.c_cflag |= CS8;
/*raw input:
* making the applycation ready to receive*/
opciones.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
/*Ignore parity errors*/
opciones.c_iflag |= ~(INPCK | ISTRIP | PARMRK);
opciones.c_iflag |= IGNPAR;
opciones.c_iflag &= ~(IXON | IXOFF | IXANY | IGNCR | IGNBRK);
opciones.c_iflag |= BRKINT;
/*raw output
* making the applycation ready to transmit*/
opciones.c_oflag &= ~OPOST;
/*aply*/
tcsetattr(sd, TCSANOW, &opciones);
mysql_init(&mysql);
mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "your_prog_name");
if (!mysql_real_connect(&mysql, argv[2], "cursoUser", "cursoPass", "cursoWasp", 0, NULL, 0)) {
fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(&mysql));
exit(-1);
} else {
fprintf(stderr, "Connected to database: return: %s\n", mysql_error(&mysql));
}
int j = 0;
int ret;
char h1[50];
char h2[50];
char mote_id[50];
char s1_id[50];
int s1_val;
char s2_id[50];
int s2_val;
char s3_id[50];
int s3_val;
while (1) {
read(sd, &c, 1);
valor[j] = c;
j++;
if ((c == '\n') || (j == (MAX - 1))) {
valor[j] = '\0';
ret = sscanf(valor, "%[^#]#%[^#]#%[^#]#%[^#]#%d#%[^#]#%d#%[^#]#%d", &h1[0], &h2[0], &mote_id[0], &s1_id[0], &s1_val, &s2_id[0], &s2_val, &s3_id[0], &s3_val);
if (ret == 9) {
fprintf(stderr, "\nWasp id: %s\n%s:%d\n%s:%d\n%s:%d\n%s:%d\n\n", mote_id, s1_id, s1_val, s2_id, s2_val, s3_id, s3_val, s4_id, s4_val);
// Create SQL insertion string.
sprintf(sql, "insert into mote_data values(NULL,now(),'%s','%s','%d','%s','%d','%s','%d');", mote_id, s1_id, s1_val, s2_id, s2_val, s3_id, s3_val);
if (mysql_query(&mysql, sql) != 0) {
fprintf(stderr, "BBDDFailed:%s\n", sql);
} else {
fprintf(stdout, "BBDDSucceeded:%s\n", sql);
}
} else {
fprintf(stderr, "\ncadena: %s\n", valor);
fprintf(stderr, "\nret:%d\nWasp id: %s\n%s:%d\n%s:%d\n%s:%d\n\n", ret, mote_id, s1_id, s1_val, s2_id, s2_val, s3_id, s3_val);
fprintf(stderr, "\nBad frame received\n");
}
j = 0;
valor[j] = '\0';
}
}
mysql_close(&mysql);
close(sd);
exit(0);
}
Finally we will make a PHP script that connects to the DDBB and shows last 25 frames received.
<?php
$BBDD_host='localhost';
$BBDD_dbuser='cursoUser';
$BBDD_dbpass='cursoPass';
$BBDD_database='cursoWasp';
function GetMyConnection()
{
global $g_link;
global $BBDD_host;
global $BBDD_dbuser;
global $BBDD_dbpass;
global $BBDD_database;
if( $g_link ){
return $g_link;
}
$g_link = mysql_connect( $BBDD_host, $BBDD_dbuser, $BBDD_dbpass) or die('Could not connect to mysql server.' );
mysql_select_db($BBDD_database, $g_link) or die('Could not select database.');
return $g_link;
}
function query($sql)
{
global $g_link;
$result = mysql_query($sql, $g_link) or die("Could not execute query $sql");
return $result;
}
$db_conn=GetMyConnection();
$sql='SELECT * FROM mote_data ORDER BY id desc limit 25 ;';
$query_result=query($sql);
$bbdd='<tr><th>Id</th><th>Date</th><th>Mote Id</th><th>Sensor</th><th>Data</th><th>Sensor</th><th>Data</th><th>Sensor</th><th>Data</th></tr>';
while ($row = mysql_fetch_assoc($query_result))
{
$bbdd.='<tr><td>'.$row['id'].'</td><td>'.$row['date'].'</td><td>'.$row['mote_id'].'</td><td>'.$row['s1_id'].'</td><td>'.$row['s1_val'].'</td><td>'.$row['s2_id'].'</td><td>'.$row['s2_val'].'</td><td>'.$row['s3_id'].'</td><td>'.$row['s3_val'].'</td></tr>';
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
<title>WSN data example</title>
</head>
<body>
<table style="text-align: left;" border="1" cellpadding="10" cellspacing="0">
<tbody>
<?=$bbdd ?>
</tbody>
</table>
</body>
</html>
Finally we will make a PHP script that connects to the DDBB and generate a CSV file with all the data received from waspmote.
<?php
$BBDD_host='localhost';
$BBDD_dbuser='cursoUser';
$BBDD_dbpass='cursoPass';
$BBDD_database='cursoWasp';
function GetMyConnection()
{
global $g_link;
global $BBDD_host;
global $BBDD_dbuser;
global $BBDD_dbpass;
global $BBDD_database;
if( $g_link ){
return $g_link;
}
$g_link = mysql_connect( $BBDD_host, $BBDD_dbuser, $BBDD_dbpass) or die('Could not connect to mysql server.' );
mysql_select_db($BBDD_database, $g_link) or die('Could not select database.');
return $g_link;
}
function query($sql)
{
global $g_link;
$result = mysql_query($sql, $g_link) or die("Could not execute query $sql");
return $result;
}
// /tmp/example_csv_file.csv will be generated but any filename can be used.
$fp=fopen('/tmp/example_csv_file.csv','w');
$db_conn=GetMyConnection();
$sql='SELECT * FROM mote_data ORDER BY id asc;';
$query_result=query($sql);
$last_id='0';
while ($row = mysql_fetch_assoc($query_result))
{
$last_id=$row['id'];
$bbdd.=$row['id'].','.$row['date'].','.$row['mote_id'].','.$row['s1_id'].','.$row['s1_val'].','.$row['s2_id'].','.$row['s2_val'].','.$row['s3_id'].','.$row['s3_val']."\n";
fwrite($fp,$bbdd);
}
fclose($fp);
?>
You can download the code of this tutorial.