passing lat/long from webserver to arduino sketch.

I have an LED matrix setup as a weather ticker, it grabs the forecast data for my area (as set in the url for weather.gov) I’d like to be able to open a webserver and change the lat / long for the url.

Is this doable?

here is the code Im currently using:

#include <ArduinoJson.h>
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>

#define HARDWARE_TYPE MD_MAX72XX::ICSTATION_HW
#define MAX_DEVICES 16
#define CLK_PIN   D5
#define DATA_PIN  D7
#define CS_PIN    D8


// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

uint8_t scrollSpeed = 25;    // default frame delay value
textEffect_t scrollEffect = PA_SCROLL_LEFT;
textPosition_t scrollAlign = PA_LEFT;
uint16_t scrollPause = 0; // in milliseconds

// Global message buffers shared by Serial and Scrolling functions
#define  BUF_SIZE  1000
char curMessage[BUF_SIZE] = { "Getting WX Data. . ." };
char newMessage[BUF_SIZE] = { "" };
bool newMessageAvailable = false;
long currentMillis = 0;

// Current fingerprint for https://api.weather.gov
const uint8_t fingerprint[20] = {0x1C, 0xE6, 0x10, 0xE0, 0x6D, 0x39, 0x26, 0x74, 0xEE, 0x44, 0x3A, 0x46, 0x9B, 0x44, 0x99, 0x77, 0xAC, 0xA3, 0xD4, 0x72};

//ESP8266WiFiMulti WiFiMulti;

void setup()
{
  Serial.begin(115200);
  P.begin();
  P.setIntensity(2);
  //Serial.println("[WiFi] Set Mode -> Station");
  //WiFi.mode(WIFI_STA);
  //delay(2000);
  //Serial.println("[WiFi] Mode = Station");
  //delay(2000);
  //delay(10);
  WiFi.begin("#####", "########");
  Serial.print("[WiFi] Connecting to My Net ...");
  //Serial.print(ssid); Serial.print(" ...");
  
  int i = 0;
  while (WiFi.status() != WL_CONNECTED) { // Wait for the Wi-Fi to connect
    delay(1000);
    Serial.print(++i); Serial.print(' ');
  }
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: \t");
    Serial.println(WiFi.localIP()); 
    getforecast();  
    P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
    //getforecast();
}

void loop()
{
  const uint32_t updatePeriod = (60L*10L*1000L);  // milliseconds in an hour
  static uint32_t lastUpdate = 0;
  if (millis() - lastUpdate >= updatePeriod) {
  
  lastUpdate = millis();
    getforecast();
  } 
  if (P.displayAnimate())
  {
    if (newMessageAvailable)
    {
      strcpy(curMessage, newMessage);
      newMessageAvailable = false;
    }
    P.displayReset();
  }
}

void getforecast()
{ 
  Serial.print("\n\nShow New Message Available Flag...");
  Serial.println(newMessageAvailable);  
  currentMillis = 0;
  std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
  client->setFingerprint(fingerprint);
  HTTPClient https;
  Serial.print("[HTTPS] begin...\n");
  if (https.begin(*client, "https://forecast.weather.gov/MapClick.php?lat=29.584&lon=-98.553&FcstType=json")) 
  {
    Serial.print("[HTTPS] GET...\n");
    int httpCode = https.GET();
    if (httpCode > 0) 
    {
    Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
    if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) 
    {
      //pass GET results to doc
      String payload = https.getString();
      //Serial.println(https.getString());  //show whole JSON feed
      const size_t capacity = 2*JSON_ARRAY_SIZE(1) + 8*JSON_ARRAY_SIZE(15) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(7) + JSON_OBJECT_SIZE(11) + JSON_OBJECT_SIZE(12) + JSON_OBJECT_SIZE(20);
      DynamicJsonDocument doc(capacity + 4500); //add in extra bytes for string duplication
      //Serial.print(" Doc Buffer Size: ");
      //Serial.println(capacity + 4500);
      deserializeJson(doc, payload);
      //DeserializationError error = deserializeJson(doc, payload);  //not using error catch for now
      //if (error) 
      //{
      //Serial.print(F("deserializeJson() failed: "));
      //Serial.println(error.c_str());
      //return;
      //}
      //Serial.print("\n\nShow New Message Available Flag...");
      //Serial.println(newMessageAvailable); 
      Serial.println("\n\nResult of buffer print");
      char CurrentPeriodBuffer[1000];  //used in ealier test
      strcpy(CurrentPeriodBuffer, doc["time"]["startPeriodName"][0].as<char*>());
      strcat(CurrentPeriodBuffer, ", ");
      strcpy(CurrentPeriodBuffer + strlen(CurrentPeriodBuffer), doc["data"]["text"][0].as<char*>());
      strcat(CurrentPeriodBuffer, " ");
      strcpy(CurrentPeriodBuffer + strlen(CurrentPeriodBuffer), doc["time"]["startPeriodName"][1].as<char*>());
      strcat(CurrentPeriodBuffer, ", ");
      strcpy(CurrentPeriodBuffer + strlen(CurrentPeriodBuffer), doc["data"]["text"][1].as<char*>());
      strcat(CurrentPeriodBuffer, "As of: ");
      strcpy(CurrentPeriodBuffer + strlen(CurrentPeriodBuffer), doc["creationDateLocal"].as<char*>());
      Serial.println(CurrentPeriodBuffer);
      strcpy(newMessage, CurrentPeriodBuffer);
      //Serial.println(newMessage);
      //Serial.print("newMessage length: ");
      //Serial.println(strlen(newMessage));
      newMessageAvailable = true;
      //Serial.print("\n\nShow New Message Available Flag...");
      //Serial.println(newMessageAvailable);
    }
    } 
    else 
    {
    Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
    }
  }
}

you can see the url “https://forecast.weather.gov/MapClick.php?lat=29.584&lon=-98.553&FcstType=json” has the lat / lon I’d like to change it to something like…
https://forecast.weather.gov/MapClick.php?lat=$lat_var$&lon=$lon_var$&FcstType=json

any help would be appreciated.

-J

If you wish to open a webserver to change those values, then your arduino had better be that webserver. Look at the examples to set it up. Once you do get those values, should should probably store them in EEPROM for future use.

You didn't say what board you are using so if it is an ESP2866, you don't have EEPROM

Sorry, yes its a WEMOS D1 Mini, I have played with the example sketches that create a webserver, and have been able to contol the BUILTIN_LED via the web page that is served up... Im just not sure how to parlay the changing of pin state to passing a variable.

-J

blh64:
You didn't say what board you are using so if it is an ESP2866, you don't have EEPROM

The ESP8266 core has the ability to emulate EEPROM using a very similar interface as AVR-based Arduinos. But, even better, it has SPIFFS.

Im just not sure how to parlay the changing of pin state to passing a variable.

It’s what you do with the data that is important. The example uses the data to control a pin state. Your code will use the data to set some variables. But, first, you have to get the data. Show your code to do that.

here is where I am at so far… I broke down the url and lat / lon into variables.
started the webserver and tried to serve up an main page with the lat / long displayed.

here is my code:

#include <ArduinoJson.h>
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
#include <WiFiClientSecureBearSSL.h>
#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>

#define HARDWARE_TYPE MD_MAX72XX::ICSTATION_HW
#define MAX_DEVICES 16
#define CLK_PIN   D5
#define DATA_PIN  D7
#define CS_PIN    D8

String lat_var = "29.584";
String lon_var = "-98.553";
#define wx_url "https://forecast.weather.gov/MapClick.php?lat="+lat_var+"&lon="+lon_var+"&FcstType=json"

//---------------------------------------------------------------
//The HTML in program memory
const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<body>
<center>
<h2>WX Ticker Lat/Lon Picker</h2>
Current Lat: <input size="8" type="text" value="+lat_var+" />


Current Lat: <input size="8" type="text" value="+lon_var+" />



<button type="button">Update</button>
</center>
</body>
</html>
)=====";
//---------------------------------------------------------------
ESP8266WebServer server(80); //Server on port 80

void handleRoot() {
 Serial.println("You called root page");
 String s = MAIN_page; //Read HTML contents
 server.send(200, "text/html", s); //Send web page
}

// HARDWARE SPI
MD_Parola P = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

uint8_t scrollSpeed = 25;    // default frame delay value
textEffect_t scrollEffect = PA_SCROLL_LEFT;
textPosition_t scrollAlign = PA_LEFT;
uint16_t scrollPause = 0; // in milliseconds

// Global message buffers shared by Serial and Scrolling functions
#define  BUF_SIZE  1000
char curMessage[BUF_SIZE] = { "Getting WX Data. . ." };
char newMessage[BUF_SIZE] = { "" };
bool newMessageAvailable = false;
long currentMillis = 0;

// Current fingerprint for https://api.weather.gov
const uint8_t fingerprint[20] = {0x1C, 0xE6, 0x10, 0xE0, 0x6D, 0x39, 0x26, 0x74, 0xEE, 0x44, 0x3A, 0x46, 0x9B, 0x44, 0x99, 0x77, 0xAC, 0xA3, 0xD4, 0x72};

//ESP8266WiFiMulti WiFiMulti;

void setup()
{
  Serial.begin(115200);
  P.begin();
  P.setIntensity(2);
  //Serial.println("[WiFi] Set Mode -> Station");
  //WiFi.mode(WIFI_STA);
  //delay(2000);
  //Serial.println("[WiFi] Mode = Station");
  //delay(2000);
  //delay(10);
  WiFi.begin("#####", "#####");
  Serial.print("[WiFi] Connecting to My Net ...");
  //Serial.print(ssid); Serial.print(" ...");
  
  int i = 0;
  while (WiFi.status() != WL_CONNECTED) { // Wait for the Wi-Fi to connect
    delay(1000);
    Serial.print(++i); Serial.print(' ');
  }
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: \t");
    Serial.println(WiFi.localIP()); 
    getforecast();  
    P.displayText(curMessage, scrollAlign, scrollSpeed, scrollPause, scrollEffect, scrollEffect);
    server.on("/", handleRoot);
}

void loop()
{
  const uint32_t updatePeriod = (60L*10L*1000L);  // milliseconds in an hour
  static uint32_t lastUpdate = 0;
  if (millis() - lastUpdate >= updatePeriod) {
  
  lastUpdate = millis();
    getforecast();
  } 
  if (P.displayAnimate())
  {
    if (newMessageAvailable)
    {
      strcpy(curMessage, newMessage);
      newMessageAvailable = false;
    }
    P.displayReset();
  }
}

void getforecast()
{ 
  Serial.print("\n\nShow New Message Available Flag...");
  Serial.println(newMessageAvailable);  
  currentMillis = 0;
  std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
  client->setFingerprint(fingerprint);
  HTTPClient https;
  Serial.print("[HTTPS] begin...\n");
  if (https.begin(*client, wx_url)) 
  {
    Serial.print("[HTTPS] GET...\n");
    int httpCode = https.GET();
    if (httpCode > 0) 
    {
    Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
    if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) 
    {
      //pass GET results to doc
      String payload = https.getString();
      //Serial.println(https.getString());  //show whole JSON feed
      const size_t capacity = 2*JSON_ARRAY_SIZE(1) + 8*JSON_ARRAY_SIZE(15) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(7) + JSON_OBJECT_SIZE(11) + JSON_OBJECT_SIZE(12) + JSON_OBJECT_SIZE(20);
      DynamicJsonDocument doc(capacity + 4500); //add in extra bytes for string duplication
      //Serial.print(" Doc Buffer Size: ");
      //Serial.println(capacity + 4500);
      deserializeJson(doc, payload);
      //DeserializationError error = deserializeJson(doc, payload);  //not using error catch for now
      //if (error) 
      //{
      //Serial.print(F("deserializeJson() failed: "));
      //Serial.println(error.c_str());
      //return;
      //}
      //Serial.print("\n\nShow New Message Available Flag...");
      //Serial.println(newMessageAvailable); 
      Serial.println("\n\nResult of buffer print");
      char CurrentPeriodBuffer[1000];  //used in ealier test
      strcpy(CurrentPeriodBuffer, doc["time"]["startPeriodName"][0].as<char*>());
      strcat(CurrentPeriodBuffer, ", ");
      strcpy(CurrentPeriodBuffer + strlen(CurrentPeriodBuffer), doc["data"]["text"][0].as<char*>());
      strcat(CurrentPeriodBuffer, " ");
      strcpy(CurrentPeriodBuffer + strlen(CurrentPeriodBuffer), doc["time"]["startPeriodName"][1].as<char*>());
      strcat(CurrentPeriodBuffer, ", ");
      strcpy(CurrentPeriodBuffer + strlen(CurrentPeriodBuffer), doc["data"]["text"][1].as<char*>());
      strcat(CurrentPeriodBuffer, "As of: ");
      strcpy(CurrentPeriodBuffer + strlen(CurrentPeriodBuffer), doc["creationDateLocal"].as<char*>());
      Serial.println(CurrentPeriodBuffer);
      strcpy(newMessage, CurrentPeriodBuffer);
      //Serial.println(newMessage);
      //Serial.print("newMessage length: ");
      //Serial.println(strlen(newMessage));
      newMessageAvailable = true;
      //Serial.print("\n\nShow New Message Available Flag...");
      //Serial.println(newMessageAvailable);
    }
    } 
    else 
    {
    Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
    }
  }
}

You seem to be under the impression that the string literal you are storing in PROGMEM will somehow contain the value that is in lat_var and the value that is in lat_lon when the page is served up. That is NOT going to happen.

You need to serve up 3 parts - the part before where the latitude and longitude values will be, the part where the latitude and longitude values will be, and the part after where the latitude and longitude values will be.

Your page needs a submit button, and you need some part of the code that deals with that button being pressed.

I was under no such impression... I was simply working in steps and as stated... that's where I was at that point in time... I got it squared away. thanks for being super helpful, the sarcasm really helps teach people who are learning a new skill...

-J