Tuesday, March 8, 2016

YellowJacket Arduino with WiShield Wifi (Part 10)

Moving Sensor Data over Wifi — 
In Part 7, a Sensor Shield was constructed and tested. The “light_temp_sensors_01” sketch sensed the sensor values and displayed the results on the Arduino Serial Monitor window on a Mac. The “Light_and_Temp_Log_to_File” sketch logged the sensed values to a file on the SD Card and displayed the results on the Arduino Serial Monitor window on a Mac.
A decision must be made about what will be done with the data. It could be collected by an Arduino and saved to an SD Card, as was done in Part 7. The SD Card can then be removed from the Arduino and the file can be copied to a computer in the computer’s SD Card port or USB reader. A second method would use ethernet or wifi to transmit the data to another computer for further processing or storage. Future blogs will examine how to:
  • Transmit the data over wifi as an http web page to a browser
  • Transmit the data over wifi as an http web page to an Arduino
  • Transmit the data over wifi from an Arduino to a Mac
  • How to store the transmitted data in a mySQL database
  • TCP/IP or UDP for data transmission
Transmit the data over wifi as an http web page to a browser
We will now examine how sensed data values will now be transmitted from one YJ Arduino using an http web page. The data elements could be transmitted as just individual numbers, or they could be transmitted as tab or comma delimited text strings, or some other un-structured format. In Parts 8 and 9, “Hello” web pages were transmitted from one YJ Arduino to another, using a local wifi infrastructure network or an adhoc network. The next example will demonstrate how use http to request sensor data and and YJ56 will respond to that request and send sensor data over wifi using an http web page as the container.
On YJ56, a button press will simulate a door being opened and triggering a switch setting. A browser request will be sent to YJ56 to report the switch setting. This could be a manual request made by a person checking on whether a door had been opened (Safari browser on Mac), or the request could be made by software on a smart phone to alert a person that a door had been opened.
Send web page from WiServer with Sensor Status
ref: https://github.com/openhomeautomation/remote-sensor-wifi/blob/master/remote_sensor_full.ino
In this sketch a push button switch is used as the sensor on YJ56. On push, send 5V0 or 3V3 to pin 3, INT1 hardware interrupt, which sets the setSensor variable. The value stays set until something is done to clear it.
boolean sensor_status = false;  // clear status
setup() {
// Attach interrupt INT1 to pin 3
attachInterrupt(1, setSensor, RISING); // setSensor=TRUE if INT1=High
The YJ56 sketch parses the incoming http request and responds based on the http request:
  • 10.0.1.56 or 10.0.1.56/ will return Hello web page.
  • 10.0.1.56/sensor will return sensor_status web page.
  • 10.0.1.56/value will return sensor value as 0 or 1 web page.
  • 10.0.1.56/reset will clear sensor_status and return web page.
/* 
 * SimpleWiServer_SensorSet_V3_01
 * A simple sketch that uses WiServer to serve a web page
 *
 * Set a sensor interupt on INT1 from push button sensor
 * Send the signal to Client as web page
*
 * This code is run with WiShield_V3 library
 * Use push button switch as sensor. On push, send 5V0 or 3V3 to pin 3, INT1, 
 * which sets the setSensor variable. The value stays set until something is done to clear it.
 * In sketch SimpleWiServer_SensorSet_V3:
 * boolean sensor_status = false;  // clear status
 * 
 * setup() { 
 *   // Attach interrupt INT1 to pin 3
 *   attachInterrupt(1, setSensor, RISING); // setSensor=TRUE if INT1=High
 * …
 * 
 * In Browser, 10.0.1.56 or 10.0.1.56/ will return Hello web page.
 * 10.0.1.56/sensor will return sensor_status web page.
 * 10.0.1.56/value will return sensor value as 0 or 1 web page.
 * 10.0.1.56/reset will clear sensor_status and return web page.
 *
 */

#include <WiServerIO.h>

#define WIRELESS_MODE_INFRA 1
#define WIRELESS_MODE_ADHOC 2

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[] = {10, 0, 1, 56}; // IP address of WiShield
unsigned char gateway_ip[] = {10, 0, 1, 1}; // router or gateway IP address
unsigned char subnet_mask[] = {255, 255, 255, 0}; // subnet mask for the local network
const char ssid[] PROGMEM = {"Network"};   // max 32 bytes

const char* myhost = "WiServer";
char* myhost_ip = "10.0.1.56";

unsigned char security_type = 3;  // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const char security_passphrase[] PROGMEM = {"Network_Passcode"};  // max 64 characters

// WEP 128-bit keys
// sample HEX keys
const uint8_t wep_keys[] PROGMEM = {  0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // Key 3
                                   };

// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

unsigned char ssid_len;
unsigned char security_passphrase_len;
//---------------------------------------------------------------------------

boolean sensor_status = false;

// This is our page serving function that generates web pages
boolean sendMyPage(char* URL) {

  // Check if the requested URL matches "/"
  if (strcmp(URL, "/") == 0) {
    // Use WiServer's print and println functions to write out the page content
    WiServer.print("<HTML>");
    WiServer.print(" >> SimpleWiServer_SensorSet_V3: Hello from Wifi MRF24 SimpleWiServer !");
    WiServer.print("<br>");
    WiServer.print(" >> SimpleWiServer_SensorSet_V3: /sensor, /value, /reset");
    WiServer.print("</HTML>");

    // URL was recognized
    return true;
  }

  // Check if the requested URL matches "/sensor"
  if (strcmp(URL, "/sensor") == 0) {
    // Use WiServer's print and println functions to write out the page content
    WiServer.print("");
    if (sensor_status) {
      WiServer.print(" >> SimpleWiServer_SensorSet_V3: Sensor has been set !");
      // clear the INT1 since the web page was returned
      //clearSensor(); // probably not good to clear status until some action is taken
    } else {
      WiServer.print(" >> SimpleWiServer_SensorSet_V3: Sensor not set !");
    }
    WiServer.print("");

    // URL was recognized
    return true;
  }

  // Check if the requested URL matches "/value"
  if (strcmp(URL, "/value") == 0) {
    // Use WiServer's print and println functions to write out the page content
    //WiServer.print("");
    if (sensor_status) {
      WiServer.print("1");
      // clear the INT1 since the web page was returned
      //clearSensor(); // probably not good to clear status until some action is taken
    } else {
      WiServer.print("0");
    }
    //WiServer.print("");

    // URL was recognized
    return true;
  }

  // Check if the requested URL matches "/reset"
  if (strcmp(URL, "/reset") == 0) {
    // Use WiServer's print and println functions to write out the page content
    WiServer.print("");
    WiServer.print("Reset Sensor Status");
    // clear the INT1 since the web page was returned
    clearSensor(); // probably not good to clear status until some action is taken
    WiServer.print("");

    // URL was recognized
    return true;
  }

  // URL not found
  return false;
}

void setSensor() {
  sensor_status = true;
  Serial.println(F("  >> Sensor Status: Activated >> "));
}

void clearSensor() {
  sensor_status = false;
  Serial.println(F("  >> Sensor Status: Cleared >> "));

}

void setup() {
  // Enable Serial output
  Serial.begin(115200);

  clearSensor();

  // Attach interrupt INT1 to pin 3
  attachInterrupt(digitalPinToInterrupt(3), setSensor, RISING);

  //
  Serial.println("");
  Serial.println(F(">> SimpleWiServer_SensorSet_V3 sketch "));
  Serial.print(F(">> WiServer.server_task initialized on "));
  Serial.print(myhost);
  Serial.print(", ip: ");
  Serial.println(myhost_ip);

  Serial.print(" Browser >> ");
  Serial.print(myhost_ip);
  Serial.print("/, ");
  Serial.print(myhost_ip);
  Serial.print("/sensor, ");
  Serial.print(myhost_ip);
  Serial.print("/value, or ");
  Serial.print(myhost_ip);
  Serial.println("/reset");
  //

  // Initialize WiServer and have it use the sendMyPage function to serve pages
  WiServer.init(sendMyPage);

  // Verbose=true >> ask WiServer to generate log messages to Serial Monitor
  WiServer.enableVerboseMode(true);

  Serial.println("");
  Serial.println(F(">> Listening for connections..."));

}

void loop() {

  // Run WiServer
  WiServer.server_task();

  delay(10);
}

Browser request: “http://10.0.1.56:80/”
>> SimpleWiServer_SensorSet_V3: Hello from Wifi MRF24 SimpleWiServer ! 
>> SimpleWiServer_SensorSet_V3: /sensor, /value, /reset
Browser request: “http://10.0.1.56:80/sensor” before and after button push on Sensor Shield
before: >> SimpleWiServer_SensorSet_V3: Sensor not set !

after: >> SimpleWiServer_SensorSet_V3: Sensor has been set !
Browser request: “http://10.0.1.56:80/reset” , then browser request “http://10.0.1.56:80/sensor”
Reset Sensor Status

>> SimpleWiServer_SensorSet_V3: Sensor not set !
Browser request: “http://10.0.1.56:80/value” before and after button push on Sensor Shield
before: 0
after:  1
Transmit the data over wifi as an http web page to an Arduino
In this example, YJ56 will be used as the http server as demonstrated above. YJ57 will send http Requests to YJ56 about the status of the sensor.
/*  
 * SimpleWiClientReadWiServer_V3_02
 *
 * A simple sketch that uses MRF24 WiClient to read web page from MRF24 WiServer
 *
 * Compiled with WiShield_V3 library
 *
 * Uses apps-conf.h "#define APP_WISERVER"
 *
 *  Connecting Two YellowJackets for Data Transfer
 *
 *  Hardware:
 *    YJ Arduino board (YJ56) at ip=10.0.1.56
 *    YJ Arduino board (YJ57) at ip=10.0.1.57
 *    Local network gateway ip 10.0.1.1
 *
 *  Example 1: WiClient YJ57 requests web page from WiServer YJ56.
 *    a) Load sketch SimpleWiServer_SensorSet_V3 into YJ56. Sketch uses
 *      “WiServer.init(sendMyPage);” to transmit web page content by Wifi.
 *    b) Load sketch SimpleWiClientReadWiServer_V3_02 into YJ57. 
 *    
 *    Un-comment one GETrequest line to obtain the desired results displayed 
 *       on Arduino Serial Monitor
 *    // Requests that return web page from server
 *    //GETrequest getWebPage(server_ip, 80, myhost_ip, "/"); // return Hello webpage
 *    //GETrequest getWebPage(server_ip, 80, myhost_ip, "/sensor"); // return sensor_status web page
 *    //GETrequest getWebPage(server_ip, 80, myhost_ip, "/value"); // return sensor_status as value
 *    //GETrequest getWebPage(server_ip, 80, myhost_ip, "/reset"); // clear sensor_status flag
 *    //GETrequest getWebPage(server_ip, 80, myhost_ip, "/json"); // request JSON formatted data
 *    
 *    c) Result: WiServer web page is requested every 10 seconds by WiClient
 *
 */

//#include <WiShield.h>
#include <WiServerIO.h> 

#define WIRELESS_MODE_INFRA 1
#define WIRELESS_MODE_ADHOC 2

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[] = {10, 0, 1, 57}; // IP address of WiShield
unsigned char gateway_ip[] = {10, 0, 1, 1}; // router or gateway IP address
unsigned char subnet_mask[] = {255, 255, 255, 0}; // subnet mask for the local network
const char ssid[] PROGMEM = {"Network"};   // max 32 bytes

const char* myhost = "WiServer";
char* myhost_ip = "10.0.1.56";

unsigned char security_type = 3;  // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const char security_passphrase[] PROGMEM = {"Network_Passcode"};  // max 64 characters

// WEP 128-bit keys
// sample HEX keys
const uint8_t wep_keys[] PROGMEM = {  0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
                                      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // Key 3
                                   };

// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;
unsigned char ssid_len;
unsigned char security_passphrase_len;

// End of wireless configuration parameters ----------------------------------------

// Function that prints data from the server
void printData(char* data, int len) {

  // Print the data returned by the server
  // Note that the data is not null-terminated, may be broken up into smaller packets, and
  // includes the HTTP header.
  while (len-- > 0) {
    Serial.print(*(data++));
  }
  Serial.println (" ."); // terminate messages with CR
}

uint8 server_ip[] = {10, 0, 1, 56}; // IP Address for WiServer YJ56
// A request that gets web page from server
GETrequest getWebPage(server_ip, 80, myhost_ip, "/"); // return Hello webpage

// For YJ56 running SimpleWiServer_SensorSet_V3 sketch:
//GETrequest getWebPage(server_ip, 80, myhost_ip, "/sensor"); // return sensor_status web page
//GETrequest getWebPage(server_ip, 80, myhost_ip, "/value"); // return sensor_status as value
//GETrequest getWebPage(server_ip, 80, myhost_ip, "/reset"); // clear sensor_status flag

// Request JSON data for 2 sensors from SimpleJsonServer_V3 sketch:
//GETrequest getWebPage(server_ip, 80, myhost_ip, "/json"); // request JSON formatted data

void setup() {

  // Enable Serial output
  Serial.begin(115200);

  Serial.println (" ");
  Serial.println (F("=== Initializing WiClient to display WiServer web page on Serial Monitor ==="));

  // Initialize WiServer (we'll pass NULL for the page serving function since we don't need to serve web pages)
  WiServer.init(NULL);

  // Ask WiServer to generate log messages (optional)
  WiServer.enableVerboseMode(true);

  // Have the processData function called when data is returned by the server
  getWebPage.setReturnFunc(printData);

  Serial.println (" ");
  Serial.println (F("=== WiClient is running... ==="));
  Serial.println (F(">>> Request response on 10 second intervals... "));
  Serial.println (" ");

}

// Time (in millis) when the data should be retrieved
unsigned long updateTime = 0;
unsigned long waitTime = 1000UL * 10UL; // * UL unsigned long number format used to avoid overflow

void loop() {

  // Check if it's time to get an update
  if (millis() >= updateTime) {
    getWebPage.submit();
    // Get another update 10 seconds from now
    updateTime += waitTime;
  }

  // Run WiServer
  WiServer.server_task();

  delay(10);
}
Serial Monitor display of “GETrequest getWebPage(server_ip, 80, myhost_ip, “/”);”
=== Initializing WiClient to display WiServer web page on Serial Monitor ===
 
=== WiClient is running... ===
>>> Request response on 10 second intervals... 
 
Connected to 10.0.1.56
TX 61 bytes
RX 0 bytes from 10.0.1.56
RX 163 bytes from 10.0.1.56
HTTP/1.0 200 OK

<html> >> SimpleWiServer_SensorSet_V3: Hello from Wifi MRF24 SimpleWiServer !<br> >> SimpleWiServer_SensorSet_V3: /sensor, /value, /reset</html> .
Ended connection with 10.0.1.56
 .
Connected to 10.0.1.56
TX 61 bytes
RX 0 bytes from 10.0.1.56
RX 163 bytes from 10.0.1.56
HTTP/1.0 200 OK

<html> >> SimpleWiServer_SensorSet_V3: Hello from Wifi MRF24 SimpleWiServer !<br> >> SimpleWiServer_SensorSet_V3: /sensor, /value, /reset</html> .
Ended connection with 10.0.1.56 
Serial Monitor display of “GETrequest getWebPage(server_ip, 80, myhost_ip, “/sensor”);” with before and after button push on YJ56 Sensor Shield:
=== Initializing WiClient to display WiServer web page on Serial Monitor ===
 
=== WiClient is running... ===
>>> Request response on 10 second intervals... 
 
Connected to 10.0.1.56
TX 67 bytes
RX 0 bytes from 10.0.1.56
RX 81 bytes from 10.0.1.56
HTTP/1.0 200 OK

<html> >> SimpleWiServer_SensorSet_V3: Sensor not set !</html> .
Ended connection with 10.0.1.56
 .
Connected to 10.0.1.56
TX 67 bytes
RX 0 bytes from 10.0.1.56
RX 86 bytes from 10.0.1.56
HTTP/1.0 200 OK

<html> >> SimpleWiServer_SensorSet_V3: Sensor has been set !</html> .
Ended connection with 10.0.1.56 
Serial Monitor display of “GETrequest getWebPage(server_ip, 80, myhost_ip, “/Reset”);”
=== Initializing WiClient to display WiServer web page on Serial Monitor ===
 
=== WiClient is running... ===
>>> Request response on 10 second intervals... 
 
Connected to 10.0.1.56
TX 66 bytes
RX 0 bytes from 10.0.1.56
RX 51 bytes from 10.0.1.56
HTTP/1.0 200 OK

<html>Reset Sensor Status</html> .
Ended connection with 10.0.1.56 
Serial Monitor display of “GETrequest getWebPage(server_ip, 80, myhost_ip, “/value”);” with before and after button push on YJ56 Sensor Shield:
=== Initializing WiClient to display WiServer web page on Serial Monitor ===
 
=== WiClient is running... ===
>>> Request response on 10 second intervals... 
 
Connected to 10.0.1.56
TX 66 bytes
RX 0 bytes from 10.0.1.56
RX 20 bytes from 10.0.1.56
HTTP/1.0 200 OK

0 .
Ended connection with 10.0.1.56
 .
Connected to 10.0.1.56
TX 66 bytes
RX 0 bytes from 10.0.1.56
RX 20 bytes from 10.0.1.56
HTTP/1.0 200 OK

1 .
Ended connection with 10.0.1.56
One problem with using http to send data is that the data are wrapped in the http response which makes extracting the data difficult.
In the next Part 11, JSON will be implemented as a means of wrapping the data in a data structure that can be more easily extracted.
(Mar 8, 2016)

No comments:

Post a Comment