Arduino web controller

From Sistemi Operativi
Jump to navigation Jump to search

Federico Giuggioloni

Programma in C che, se richiamato da PHP, permette di controllare l'arduino da remoto, in questo esempio ho solo aggiunto la funzione per mandare il segnale HIGH o LOW ai primi 9 pin attraverso il comando SEND n. se n e' minore di 10 manda a LOW al numero specificato, se e' di 10 e minore di 20 manda HIGH al pin specificato dalla seconda cifra.

Sketch Arduino:

int incomingByte = -1;

void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600);  //57600
  
  pinMode(8, OUTPUT);
  
  Serial.println("Hello world!");
}
 
void loop() // run over and over
{
  if (Serial.available() > 0)
  {
    incomingByte = Serial.read();
    Serial.print("I received: ");
    Serial.println(incomingByte, DEC);
    
    if( incomingByte < 10 )
    {
       digitalWrite(incomingByte, LOW); 
    }
    else if(incomingByte < 20)
    {
       digitalWrite(incomingByte-10, HIGH);
    }
  }
}

Programma in C che interpreta i comandi e invia un numero all'arduino corrispondente alla azione da intraprendere:

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#define MAXIMUM_CHAIN 16

void usage()
{
   printf("Usage:\n\tarduino-controller /dev/ttyUSBX\nWhere X depends on which port arduino is connected to\n");
   exit(1);
}

void checkError(int result)
{
   if(result < 0)
   {
      printf("Error: %s (%i)\n", strerror(errno), errno);
      exit(1);
   }
}

/**
 * strspl
 * @author Federico Giuggioloni
 * Splits a string and allocates memory for an array
 * which contains the result of the split.
 *
 * @param char*** split a pointer to a string array,
 *          can be null. after the call, it'll be an
 *          array with the required elements.
 * @param char* string a pointer to the string to split
 * @param const char* delim a pointer to the delimiter.
 * @return number of elements in the split array
 */
int strspl(char*** split, char* string, const char* delim)
{
   char* result;
   char* parsed = malloc(strlen(string)+1);
   char* tofree = parsed;

   if(*split == NULL)
   {
      *split = malloc(sizeof(char*) * MAXIMUM_CHAIN);
   }

   strcpy(parsed, string);

   int i = 0;
   while((result = strtok(parsed, delim)) != NULL)
   {
      //subsequent calls to strtok must have NULL in the first
      //parameter
      parsed = NULL;

      //(*split)[i] = result;
      (*split)[i] = malloc(strlen(result) * sizeof(char) + 1);
      strcpy((*split)[i], result);

      printf("%s\n", result);

      i++;
   }

   free(tofree);
   return i;
}

/**
 * read_commands
 * @author Federico Giuggioloni
 * Reads commands from an array produced by strspl
 *
 * @return integer determining which action has to be executed
 *          (HINTHINT Send it directly to arduino)
 */
char read_commands(char** commands, int argc)
{
   int action = 0;
   int pin;

   if(strcmp(commands[0], "LED") == 0)
   {
      if(strcmp(commands[1], "ON") == 0)
      {
         pin = atoi(commands[2]);
         action = 10 + pin;
      }
      else if(strcmp(commands[2], "OFF") == 0)
      {
         pin = atoi(commands[2]);
         action = 0 + pin;
      }
   }
   else if(strcmp(commands[0], "SEND") == 0)
   {
      action = atoi(commands[1]);
   }

   return action;//TODO
}

int main(int argc, char* argv[])
{
   if(argc < 1) usage();

   int fd;
   int i;
   char* message;
   size_t size = 1024;
   int read;
   char** split = NULL;
   int tokens;
   char delim = ' ';
   char read_command = 0;

   message = malloc(size);

   fd = open(argv[1], O_RDWR);
   checkError(fd);

   if(argc > 2)
   {
      read_command = read_commands(argv+2, argc-2);
      write(fd, &read_command, 1);
      exit(0);
   }

   do
   {
      read = getline(&message, &size, stdin);

      tokens = strspl(&split, message, &delim);

      read_command = read_commands(split, tokens);
      write(fd, &read_command, 1);

   }while(1);

   return 0;
}

Script PHP che usa la exec per eseguire il programma C. Richiede pero' i permessi al file di arduino in /dev e al programma C, altrimenti restituisce permission denied.

<?php

if(isset($_GET["script"]) && isset($_GET["args"]))
{
   $result = exec($_GET["script"]." ".$_GET["args"]."", $output, $return);
      echo $_GET["script"]." ".$_GET["args"]." called, result = $result!<br/>";

      if(!$return)
      {
         echo "Succesful!<br/>";
      }
      else
      {
         echo "No.<br/>";
      }

      echo "$output<br/>";
      echo "$result<br/>";
}

?>