Go Down

Topic: Use a arduino variable in a local webserver (Read 617 times) previous topic - next topic

Royvanempel

Hello,

I have been working on a school project which is supposed to be a piece of an Escape Room. The Arduino i am working with(esp8266) is supposed to create a Wifi hotspot with a captive portal so it will automatically open a webpage when you connect. While starting it makes an SQL connection which is running on a server and it will retrieve a 'Code' from a database. Then when the client connects he needs to put in a code and the Input will be compared to the 'Code'. The problem i am currently having is that i am not able to get the Arduino variable to the html/js page so i can compare it. if someone knows how to do something like this with Arduino please give me some suggestions or if there are better ways of doing something like this.

Greetings,
Roy

PaulS

Quote
The problem i am currently having is that i am not able to get the Arduino variable to the html/js page so i can compare it.
Which Arduino variable? Can't you see that it WILL be necessary to post your code?
The art of getting good answers lies in asking good questions.

Royvanempel

Sorry for not adding the code Here it is https://pastebin.com/raw/aFMYKeRQ

The arduino variable is a "code" retrieved from a database.

PaulS

Quote
Here it is
Post your code HERE, not in the rubbish bin.
The art of getting good answers lies in asking good questions.

Royvanempel

Post your code HERE, not in the rubbish bin.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>

#include "lwip/lwip_napt.h"
#include "lwip/app/dhcpserver.h"
#include "lwip/netif.h"
#include "netif/etharp.h"
#include "lwip/udp.h"
#include "index.h" //Our HTML webpage contents
#include "pass.h" //Our HTML webpage contents
#include "passding.h"

// credentials for ESP8266 STA
const char* sta_ssid = "##################";
const char* sta_password = "##################";
String s = MAIN_page;
String v = PASS_page;
// name of the ESP8266 AP
#define AP_SSID "##################"

const int MAX_CLIENTS = 16;


byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

IPAddress server_addr(##################);  // IP of the MySQL *server* here
char user[] = "##################";              // MySQL user login username
char password[] = "##################";        // MySQL user login password

WiFiClient client;            // Use this for WiFi instead of EthernetClient
MySQL_Connection conn((Client *)&client);

#define VIEWPORT "<meta name='viewport' content='width=device-width, initial-scale=1'>"

String acceptedHTML = "<!DOCTYPE html>"
"<html>"
    "<head>"
      "<title>" AP_SSID "</title>"
    "</head>"
    VIEWPORT
    "<meta http-equiv=\"refresh\" content=\"3;url=http://www.google.com/\" />"
    "<body>"
      "<h1>Terms accepted!</h1>"
    "</body>"
"</html>";

const byte DHCP_PORT = 67;
const byte DNS_PORT = 53;
const byte HTTP_PORT = 80;

IPAddress myIP;
ESP8266WebServer webServer(80);


PACK_STRUCT_BEGIN
struct tcp_hdr {
  PACK_STRUCT_FIELD(u16_t src);
  PACK_STRUCT_FIELD(u16_t dest);
  PACK_STRUCT_FIELD(u32_t seqno);
  PACK_STRUCT_FIELD(u32_t ackno);
  PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
  PACK_STRUCT_FIELD(u16_t wnd);
  PACK_STRUCT_FIELD(u16_t chksum);
  PACK_STRUCT_FIELD(u16_t urgp);
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END

// some magic from inside the NAT lwip for address rewriting
extern "C" {
  void ip_napt_modify_addr_tcp(struct tcp_hdr *tcphdr, ip_addr_p_t *oldval, u32_t newval);
  void ip_napt_modify_addr(struct ip_hdr *iphdr, ip_addr_p_t *field, u32_t newval);
}

static netif_input_fn orig_input_ap;
static netif_linkoutput_fn orig_output_ap;
struct eth_addr curr_mac;
uint32_t curr_IP;

struct eth_addr allowed_macs[MAX_CLIENTS];
int max_client = 0;

bool check_packet_in(struct pbuf *p) {
struct eth_hdr *mac_h;
struct ip_hdr *ip_h;
struct udp_hdr *udp_he;
struct tcp_hdr *tcp_h;

  if (p->len < sizeof(struct eth_hdr))
    return false;

  mac_h = (struct eth_hdr *)p->payload;

  // Check only IPv4 traffic
  if (ntohs(mac_h->type) != ETHTYPE_IP)
    return true;

  if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr))
    return false;

  ip_h = (struct ip_hdr *)(p->payload + sizeof(struct eth_hdr));

  // Known MACs can pass
  for(int i = 0; i<max_client; i++) {
    if (memcmp(mac_h->src.addr, allowed_macs.addr, sizeof(mac_h->src.addr)) == 0) {
      return true;
    }
  }

  // DHCP and DNS is okay
  if (IPH_PROTO(ip_h) == IP_PROTO_UDP) {
    if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr)+sizeof(struct udp_hdr))
      return false;

    udp_he = (struct udp_hdr *)(p->payload + sizeof(struct eth_hdr) + sizeof(struct ip_hdr));

    if (ntohs(udp_he->dest) == DHCP_PORT)
      return true;

    if (ntohs(udp_he->dest) == DNS_PORT)
      return true;

    return false;
  }

  // HTTP is redirected
  if (IPH_PROTO(ip_h) == IP_PROTO_TCP) {
    if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr)+sizeof(struct tcp_hdr))
      return false;

    tcp_h = (struct tcp_hdr *)(p->payload + sizeof(struct eth_hdr) + sizeof(struct ip_hdr));

    if (ntohs(tcp_h->dest) == HTTP_PORT) {
      curr_mac = mac_h->src;
      curr_IP = ip_h->dest.addr;
      ip_napt_modify_addr_tcp(tcp_h, &ip_h->dest, (uint32_t)myIP);
      ip_napt_modify_addr(ip_h, &ip_h->dest, (uint32_t)myIP);
      return true;
    }
  }

  // drop anything else
  return false;
}

err_t my_input_ap (struct pbuf *p, struct netif *inp) {

  if (check_packet_in(p)) {
    return orig_input_ap(p, inp);
  } else {
    pbuf_free(p);
    return ERR_OK;
  }
}

bool check_packet_out(struct pbuf *p) {
struct eth_hdr *mac_h;
struct ip_hdr *ip_h;
struct tcp_hdr *tcp_h;

  if (p->len < sizeof(struct eth_hdr)+sizeof(struct ip_hdr)+sizeof(struct tcp_hdr))
    return true;

  ip_h = (struct ip_hdr *)(p->payload + sizeof(struct eth_hdr));

  if (IPH_PROTO(ip_h) != IP_PROTO_TCP)
    return true;

  tcp_h = (struct tcp_hdr *)(p->payload + sizeof(struct eth_hdr) + sizeof(struct ip_hdr));

  // rewrite packet from our HTTP server
  if (ntohs(tcp_h->src) == HTTP_PORT && ip_h->src.addr == (uint32_t)myIP) {
    ip_napt_modify_addr_tcp(tcp_h, &ip_h->src, curr_IP);
    ip_napt_modify_addr(ip_h, &ip_h->src, curr_IP);
  }

  return true;
}

err_t my_output_ap (struct netif *outp, struct pbuf *p) {

  if (check_packet_out(p)) {
    return orig_output_ap(outp, p);
  } else {
    pbuf_free(p);
    return ERR_OK;
  }
}

// patches the netif to insert the filter functions
void patch_netif(ip_addr_t netif_ip, netif_input_fn ifn, netif_input_fn *orig_ifn, netif_linkoutput_fn ofn, netif_linkoutput_fn *orig_ofn)
{
struct netif *nif;

  for (nif = netif_list; nif != NULL && nif->ip_addr.addr != netif_ip.addr; nif = nif->next);
  if (nif == NULL) return;

  if (ifn != NULL && nif->input != ifn) {
    *orig_ifn = nif->input;
    nif->input = ifn;
  }
  if (ofn != NULL && nif->linkoutput != ofn) {
    *orig_ofn = nif->linkoutput;
    nif->linkoutput = ofn;
  }
}

void setup()
{
  Serial.begin(115200);
  Serial.println();

  WiFi.mode(WIFI_AP_STA);

  Serial.println("Connecting to STA");

  WiFi.begin(sta_ssid, sta_password);

  //Wifi connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(sta_ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("dnsIP address: ");
  Serial.println(WiFi.dnsIP());
  Serial.print("gatewayIP address: ");
  Serial.println(WiFi.gatewayIP());
  Serial.print("subnetMask address: ");
  Serial.println(WiFi.subnetMask());


  Serial.println("");
  Serial.println("Configuring access point...");
  WiFi.softAP(AP_SSID, NULL, 1, 0, 8);

  myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);

  // Insert the filter functions
  patch_netif(myIP, my_input_ap, &orig_input_ap, my_output_ap, &orig_output_ap);

  // Initialize the NAT feature
  ip_napt_init(IP_NAPT_MAX, IP_PORTMAP_MAX);

  // Enable NAT on the AP interface
  ip_napt_enable_no(1, 1);

  // Set the DNS server for clients of the AP to the one we also use for the STA interface
  dhcps_set_DNS(WiFi.dnsIP());





Serial.println("Connecting To MySQL Database");
  if (conn.connect(server_addr, 3306, user, password)) {
    delay(1000);
  }
  else
    Serial.println("Connection failed.");
 
  char query[] = "SELECT code FROM gilde.code LIMIT 1";

  Serial.println("\nRunning SELECT from CODE and printing results\n");

  // Initiate the query class instance
  MySQL_Cursor *cur_mem = new MySQL_Cursor(&conn);
  // Execute the query with the PROGMEM option
  cur_mem->execute(query, true);
  // Show the results
  //cur_mem->show_results();
  // Deleting the cursor also frees up memory used

  column_names *cols = cur_mem->get_columns();   
  Serial.println();
  row_values *row = NULL;
  row = cur_mem->get_next_row();

  Serial.println("\nThe Code:");

  String thecode = row->values[0];
  Serial.println(thecode);

  Serial.println("\nVerwijder SQL Memory");
  delete cur_mem;
  conn.close();












  webServer.on("/", []() {
    webServer.send(200, "text/html", s);
  });
  webServer.on("/pass", []() {
    webServer.send(200, "text/html", v);
  });

  webServer.on("/accepted", []() {
    for (int i = 0; i < 6; i++) {
      Serial.print(curr_mac.addr);Serial.print(":");
    }
    Serial.println(" allowed");

    if (max_client < MAX_CLIENTS) {
      allowed_macs[max_client++] = curr_mac;
    }
    webServer.send(200, "text/html", acceptedHTML);
  });

  // redirect all other URIs to our "/"
  webServer.onNotFound([]() {
    webServer.sendHeader("Location", String("http://")+myIP.toString()+String("/"), true);
    webServer.send (302, "text/plain", "");
  });
  webServer.begin();




}

void loop()
{
  webServer.handleClient();
}

PaulS

Which variable (theCode that is local to setup()?) do you want to use?

Where?





















Why is there so much white space in your













code?
The art of getting good answers lies in asking good questions.

Royvanempel

Which variable (theCode that is local to setup()?) do you want to use?

Where?





















Why is there so much white space in your













code?
The white space is just how i work. It's for my self to remember where everything is. after something is done i always go and remove them.


thecode is before the 12 white spaces so where its retrieves it from the database. This:
String thecode = row->values[0];

currently nothing is being done with it since i have no idea how to get it to an html file. The html file is the #include "index.h" at the top.

PaulS

Quote
currently nothing is being done with it since i have no idea how to get it to an html file.
The first step is to get the variable in the proper scope (global) so that its value CAN be used.

The second step involves showing us the contents of this mysterious file.
The art of getting good answers lies in asking good questions.

Royvanempel

The mysterious file is a simple html file with a background.
Isn't anything more

PaulS

The mysterious file is a simple html file with a background.
Isn't anything more
You can NOT #include an html file in C++ code. There MUST be more to it.

If posting it is too much to ask, you'll need to figure out how to use the value from the variable yourself.
The art of getting good answers lies in asking good questions.

Royvanempel

Thank you, You are not helpfull you are only making fun of how i work and what i do. comment on everything and in the html file there simply is this in front of it:
const char MAIN_page[] PROGMEM = R"=====(

and this after the html:
)=====";

Goodbye and thanks for your help..........

PaulS

Quote
there simply is this in front of it:
That const means that you can not change the data. You need to completely change your approach.

Create the html data in three parts - the stuff before where you want variable output, the variable output section, and the stuff after the variable output section.

As to specifically how to do that, I can't help you because that file is apparently top secret.
The art of getting good answers lies in asking good questions.

Go Up