Arduino + Ethernet Shield + 16x2 LCD + Powershell

I have been playing with this the last couple days and finally got it to work. The title pretty much says it all. I have an Arduino with an Ethernet shield that receives requests from PowerShell that is querying the computer for RAM and CPU usage. I am really new to Arduino, but I figured this might help somebody. I have to give credit to hari http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1284844153. He posted some web server code that I modified to make my project work.

I literally just got it working so it may be a little rough. Take it easy :stuck_out_tongue:

Here is the Arduino code:

/*
 Arduino Data Web Server

 Performs actions on Arduino and/or returns data from Arduino to a webbrowser request URL:
  - To turn on LED on pin 8, use web browser to visit your Arduino via: http://x.x.x.x/digitalWrite/7/1
  - To turn it off send: http://x.x.x.x/digitalWrite/7/0
  - To read analog0 value, send: http://x.x.x.x/analogRead/0

 IMPORTANT:
 Commands are case sensitive, but I wrote this as simple as possible so it can be easily adapted to your needs.  
 Have fun!

 created Sept 17, 2010
 by Hari Wiguna, g33k.blogspot.com
*/

/*
I have modified the original Arduino Data Web Server code by Hari. Please see his site above for the original.  
*/


// include the library code:
#include <LiquidCrystal.h>
#include <SPI.h>
#include <Ethernet.h>
#include <string.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

byte mac[] = {0x90, 0xA2, 0xDA, 0x00, 0x33, 0x3A };
byte ip[] = {192.168.1.1}; // IP Address of arduino

Server server(80); // Port 80 is http.

//Command Parameters
char cmd[15];  
char param1[15];
char param2[15];

#define bufferMax 128
int bufferSize;
char buffer[bufferMax];

void setup() {
  //Ethernet
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.begin(9600);
  
  Serial.println("Starting serial debugging at 9600");
  lcd.setCursor(0,0);
  lcd.begin(16, 2);
}

void loop() {
  Client client = server.available();
  if (client)
  {
    WaitForRequest(client);
    ParseReceivedRequest();
    PerformRequestedCommands();
    client.stop();
  }
}

void WaitForRequest(Client client) // Sets buffer[] and bufferSize
{
  bufferSize = 0;

  while (client.connected()) {
    if (client.available()) {
      char c = client.read();
      if (c == '\n')
        break;
      else
        if (bufferSize < bufferMax)
          buffer[bufferSize++] = c;
        else
          break;
    }
  }
  PrintNumber("bufferSize", bufferSize);
}

void ParseReceivedRequest()
{
  Serial.println("in ParseReceivedRequest");
  Serial.println(buffer);
  
  //Received buffer contains "GET /cmd/param1/param2 HTTP/1.1".  Break it up.
  char* slash1;
  char* slash2;
  char* slash3;
  char* space2;
  
  slash1 = strstr(buffer, "/") + 1; // Look for first slash
  slash2 = strstr(slash1, "/") + 1; // second slash
  slash3 = strstr(slash2, "/") + 1; // third slash
  space2 = strstr(slash2, " ") + 1; // space after second slash (in case there is no third slash)
  if (slash3 > space2) slash3=slash2;

  PrintString("slash1",slash1);
  PrintString("slash2",slash2);
  PrintString("slash3",slash3);
  PrintString("space2",space2);
  
  // strncpy does not automatically add terminating zero, but strncat does! So start with blank string and concatenate.
  cmd[0] = 0;
  param1[0] = 0;
  param2[0] = 0;
  strncat(cmd, slash1, slash2-slash1-1);
  strncat(param1, slash2, slash3-slash2-1);
  strncat(param2, slash3, space2-slash3-1);
  
  PrintString("cmd",cmd);
  PrintString("param1",param1);
  PrintString("param2",param2);
}

void PerformRequestedCommands()
{
  if ( strcmp(cmd,"CPU") == 0 ) PrintCPU(); //This used to be a digitalwrite and digitalread
  if ( strcmp(cmd,"RAM") == 0 ) PrintRAM();
}

void PrintCPU()  
{
  int stars = param1[0] - '0';
  PrintNumber("stars",stars);
  
  lcd.setCursor(0,0);
  lcd.print("CPU:[");
  
  lcd.setCursor(5, 0); //CPU
  
  if(stars == 0)
  {
    lcd.print("**********");
  }
  else
  {
    for(int x=0;x<stars;x++)
    {
      lcd.print("*");
    }
    for(int x=stars;x<11;x++)
    {
      lcd.print(" ");
    }
  }
  lcd.setCursor(15,0);
  lcd.print("]");   //closing bracket
  
  Serial.println("CPU Data recieved.");
  server.print("CPU data recieved.");
}

void PrintRAM()
{
  int stars = param1[0] - '0';
  PrintNumber("stars",stars);
  
  lcd.setCursor(0,1);
  lcd.print("RAM:[");
  
  lcd.setCursor(5, 1); //RAM
  
  if(stars == 0)
  {
    lcd.print("**********");
  }
  else
  {
    for(int x=0;x<stars;x++)
    {
      lcd.print("*");
    }
    for(int x=stars;x<11;x++)
    {
      lcd.print(" ");
    }
  }
  lcd.setCursor(15,1);
  lcd.print("]");   //closing bracket
  
  Serial.println("RAM Data recieved.");
  server.print("RAM data recieved.");
}

void PrintString(char* label, char* str)
{
  Serial.print(label);
  Serial.print("=");
  Serial.println(str);
}

void PrintNumber(char* label, int number)
{
  Serial.print(label);
  Serial.print("=");
  Serial.println(number, DEC);
}

Here is the PowerShell code:

#This gets the performance of local computer and sends it to arduino board
While($x -ne 0)
{
    Get-Performance
    Start-Sleep -s 10   #this will run the powershell script every 10 seconds.
}


Function Get-Performance(){
$CPU = Get-WmiObject win32_processor | Measure-Object -property LoadPercentage -Average | Select Average
 
$SystemInfo = Get-WmiObject -Class Win32_OperatingSystem | Select-Object Name, TotalVisibleMemorySize, FreePhysicalMemory
$perRam = (($SystemInfo.FreePhysicalMemory/1MB) / ($systeminfo.totalvisiblememorysize/1MB)) * 100
$perRam = 100 - $perRam

Write-host ("CPU:  " + $CPU.Average + "%")
Write-host ("Ram:  " + $perRam + "%")

$CPUStars = $CPU.Average / 10
$RAMStars = $perRam /10

if($CPUStars -lt 1){$CPUStars = 1}

Write-host ("{0:N0}" -f $CPUStars)
Write-host ("{0:N0}" -f $RAMStars)

$evalCPUStars = "{0:N0}" -f $CPUStars
$evalRAMStars = "{0:N0}" -f $RAMStars

$server = "<put your IP of the arduino here>"

#this will get our page for later
$cpuPage = (New-Object System.Net.WebClient).DownloadString("http://" + $server + "/CPU/" + $evalCPUStars)
$ramPage = (New-Object System.Net.WebClient).DownloadString("http://" + $server + "/RAM/" + $evalRAMStars)
Write-host("http://" + $server + "/CPU/" + $evalCPUStars)
Write-host("http://" + $server + "/RAM/" + $evalRAMStars)
}

Hope this helps someone. Feel free to do whatever you want with it. :slight_smile:

Here is a picture to show it in action.

  if (slash3 > space2) slash3=slash2;

What? You are checking to see if one pointer is greater than another? You haven't even checked to see that the pointers are valid.

  slash1 = strstr(buffer, "/") + 1; // Look for first slash
  slash2 = strstr(slash1, "/") + 1; // second slash
  slash3 = strstr(slash2, "/") + 1; // third slash
  space2 = strstr(slash2, " ") + 1; // space after second slash (in case there is no third slash)

You should not be passing slash1 to strstr() unless you have validated that it is a valid pointer. Ditto for slash2.

PaulS:

  if (slash3 > space2) slash3=slash2;

What? You are checking to see if one pointer is greater than another? You haven't even checked to see that the pointers are valid.

  slash1 = strstr(buffer, "/") + 1; // Look for first slash

slash2 = strstr(slash1, "/") + 1; // second slash
 slash3 = strstr(slash2, "/") + 1; // third slash
 space2 = strstr(slash2, " ") + 1; // space after second slash (in case there is no third slash)



You should not be passing slash1 to strstr() unless you have validated that it is a valid pointer. Ditto for slash2.

Also, you generally should not be using strstr, particularly for searching for a single character. Strchr will search for a single character, which is an int value (i.e. use single quotes, not double quotes).

So instead of:

ptr = strstr (buffer, "/");

Do:

ptr = strchr (buffer, '/');

Now, lets see. I assume you can overwrite the slashes in the string will null's. If you need to restore the buffer to its original value, you would need to restore them at the end.

const int NUM_SLASHES = 3;

void ParseReceivedRequest()
{
    char *slash[NUM_SLASHES] = { NULL, NULL, NULL };
    int slash_num = 0;
    char *p;
    char *space = NULL;
    char *current = buffer;

    Serial.println("in ParseReceivedRequest");
    Serial.println(buffer);
  
    // If we couldn't parse the command, make sure we have empty strings
    cmd[0] = '\0';
    param1[0] = '\0';
    param2[0] = '\0';

    // Received buffer contains "GET /cmd/param1/param2 HTTP/1.1".  Break it up.
    while ((p = strchr (current)) != NULL && slash_num < NUM_SLASHES)
        {
            // Replace / with null byte so it can be used as a string
            *p = '\0';
            slash[slash_num++] = current;
            current = p+1;
        }

    if (p != NULL)
        {
             Serial.println ("Too many /'s");
        }
    else if (slash_num != NUM_SLASHES-1)
        {
              Serial.print ("Expected ");
              Serial.print (NUM_SLASHES);
              Serial.print ("/'s, got ");
              Serial.println (slash_num + 1);
        }
    else
        {
             space = strchr (slash[slash_num-1], ' ');
             if (space == NULL)
                 {
                      Serial.println ("No space after last /");
                  }
            else
                {
                     // replace space with null
                     *space = '\0'

                     PrintString ("Cmd", slash[0]);
                     PrintString ("Param1", slash[1]);
                     PrintString ("Param2", slash[2]);

                     strcpy (cmd, slash[0]);
                     strcpy (param1, slash[1]);
                     strcpy (param2, slash[2]);
                }
        }

    // Now in general, you probably don't need to worry about having
    // the original values in them.  If you do, uncomment this code.
    //for (int i = 0; i < slash_num; i++)
    //    {
    //        *slash[i] = '/';
    //    }
    //if (space != NULL)
    //    {
    //        *space = ' ';
    //    }
}

Can some one post a complete correction to the code please I tried to follow a long but got lost.

Thanks