Sanyaade  Adekoya
Published © MIT

PHP Embedded (PHP4MCU)

I started thinking about how to get a PHP framework to work on a small mid-range microcontroller like ESP8266 family, ARM cortex & PIC MCUs.

IntermediateWork in progress4,682
PHP Embedded (PHP4MCU)

Things used in this project

Hardware components

ESP8266 ESP-01
Espressif ESP8266 ESP-01
×1
ESP8266 ESP-12E
Espressif ESP8266 ESP-12E
×1
STMicroelectronics STM32F4VET6
×1

Software apps and online services

NodeMCU firmware
NodeMCU firmware
ESP8266 Open SDK
SMING ESP8266 SDK
Mongoose OS
Mongoose OS
PH7 - PHP Interpreter

Hand tools and fabrication machines

Allen Wrench
OpenBuilds Allen Wrench
Jumper Wires Dupont
Various types according to your need

Story

Read more

Schematics

PHP4MCU Block Diagram (Software Components)

Software Components Block Diagram

Code

WebServer with CGI Interface (webserver.c) WIP

C/C++
This code implements our Webserver with CGI interface so that we can pass .php file to a php cgi binary to parse, compile and return output back to Webserver. Save it as webserver.c in your project folder. We will be adding, removing and adapting on this as time goes on in our series and parts to follow.
// Copyright (c) 2015 Cesanta Software Limited
// All rights reserved

// Copyright (c) Copyright (C) 2011,2012,2013,2014,2015,2016,2017 Symisc Systems.

// Copyright (c) SanyaadeAdekoya(Pat-Eta Electronics Ltd). MIT license


#include "mongoose.h"


struct device_settings {
  char setting1[100];
  char setting2[100];
};

static const char *s_http_port = "8000";
static struct mg_serve_http_opts s_http_server_opts;
static struct device_settings s_settings = {"value1", "value2"};

// const char *cgi_interpreter = "/home/sanyaade/Downloads/WebServers/Embedded-Systems/Mongoose/Packages/mongoose-master/examples/myServer/ifj";

static void handle_save(struct mg_connection *nc, struct http_message *hm) {
  // Get form variables and store settings values
  mg_get_http_var(&hm->body, "setting1", s_settings.setting1,
                  sizeof(s_settings.setting1));
  mg_get_http_var(&hm->body, "setting2", s_settings.setting2,
                  sizeof(s_settings.setting2));

  // Send response
  mg_http_send_redirect(nc, 302, mg_mk_str("/"), mg_mk_str(NULL));
}

static void handle_get_cpu_usage(struct mg_connection *nc) {
  // Generate random value, as an example of changing CPU usage
  // Getting real CPU usage depends on the OS.
  int cpu_usage = (double) rand() / RAND_MAX * 100.0;

  // Use chunked encoding in order to avoid calculating Content-Length
  mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");

  // Output JSON object which holds CPU usage data
  mg_printf_http_chunk(nc, "{ \"result\": %d }", cpu_usage);

  // Send empty chunk, the end of response
  mg_send_http_chunk(nc, "", 0);
}

static void handle_ssi_call(struct mg_connection *nc, const char *param) {
  if (strcmp(param, "setting1") == 0) {
    mg_printf_html_escape(nc, "%s", s_settings.setting1);
  } else if (strcmp(param, "setting2") == 0) {
    mg_printf_html_escape(nc, "%s", s_settings.setting2);
  }
}

static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
  struct http_message *hm = (struct http_message *) ev_data;

  switch (ev) {
    case MG_EV_HTTP_REQUEST:
      if (mg_vcmp(&hm->uri, "/save") == 0) {
        handle_save(nc, hm);
      } else if (mg_vcmp(&hm->uri, "/get_cpu_usage") == 0) {
        handle_get_cpu_usage(nc);
      } else {
        mg_serve_http(nc, hm, s_http_server_opts);  // Serve static content
      }
      break;
    case MG_EV_SSI_CALL:
      handle_ssi_call(nc, ev_data);
      break;
    default:
      break;
  }
}

static void push_data_to_all_websocket_connections(struct mg_mgr *m) {
  struct mg_connection *c;
  int memory_usage = (double) rand() / RAND_MAX * 100.0;

  for (c = mg_next(m, NULL); c != NULL; c = mg_next(m, c)) {
    if (c->flags & MG_F_IS_WEBSOCKET) {
      mg_printf_websocket_frame(c, WEBSOCKET_OP_TEXT, "%d", memory_usage);
    }
  }
}

int main(void) {
  struct mg_mgr mgr;
  struct mg_connection *nc;
  cs_stat_t st;
  cs_stat_t cgi_st;

  mg_mgr_init(&mgr, NULL);
  nc = mg_bind(&mgr, s_http_port, ev_handler);
  if (nc == NULL) {
    fprintf(stderr, "Cannot bind to %s\n", s_http_port);
    exit(1);
  }

  // Set up HTTP server parameters
  mg_set_protocol_http_websocket(nc);
  s_http_server_opts.document_root = "web_root";  // Set up web root directory
  if (mg_stat(s_http_server_opts.document_root, &st) != 0) {
    fprintf(stderr, "%s", "Cannot find web_root directory, exiting\n");
    exit(1);
	}
    
  //mg_serve_http( opts.cgi_interpreter = "ph7_interp");
  // opts.cgi_interpreter = "ph7_interp" ;
  // mg_serve_http_opts.cgi_interpreter = "ph7_interp"
  s_http_server_opts.cgi_interpreter = "/home/sanyaade/Downloads/WebServers/Embedded-Systems/Mongoose/Packages/mongoose-master/examples/myServer/ph7_cgi";	//set up cgi-interpreter directory
  if (mg_stat(s_http_server_opts.cgi_interpreter, &cgi_st) != 0) {
    fprintf(stderr, "%s", "Cannot find cgi_interpreter directory, exiting\n");
    exit(1);
  }

  printf("Starting web server on port %s\n", s_http_port);
  for (;;) {
    static time_t last_time;
    time_t now = time(NULL);
    mg_mgr_poll(&mgr, 1000);
    if (now - last_time > 0) {
      push_data_to_all_websocket_connections(&mgr);
      last_time = now;
    }
  }
  mg_mgr_free(&mgr);

  return 0;
}

Webserver (based on feature rich Mongoose being modified WIP)

Our Webserver based platform this is needed for out project. Download Mongoose.c and Mongoose.h from the link above or below. Save them into the same folder where you have saved the Webserver.c file.

PH7 Interpreter (A custom hand written PHP interpreter by symisc.net)

Our PHP interpreter need for project. Download ph7.c and ph7.h from the link below. Save them into the same folder where you have saved the Webserver.c file.

Credits

Sanyaade  Adekoya

Sanyaade Adekoya

18 projects • 55 followers
Lecturer/Developer/Programmer

Comments