Arduino Json - Sunrise/Sunset

Hi blynkers i want to have Sunrise and Sunset command line so i receive this from API:

{"results":{"sunrise":"6:19:31 AM","sunset":"5:50:31 PM","solar_noon":"12:05:01 PM","day_length":"11:31:00","civil_twilight_begin":"5:53:42 AM","civil_twilight_end":"6:16:20 PM","nautical_twilight_begin":"5:23:45 AM","nautical_twilight_end":"6:46:17 PM","astronomical_twilight_begin":"4:53:44 AM","astronomical_twilight_end":"7:16:17 PM"},"status":"OK"}

How can i convert this string code to json readable for ArduinoJson Library like as bellow:

{\"results\":{\"sunrise\":\"3:34:07 AM\",\"sunset\":\"3:23:09 PM\",\"solar_noon\":\"9:28:38 AM\",\"day_length\":\"11:49:02\",\"civil_twilight_begin\":\"3:09:26 AM\",\"civil_twilight_end\":\"3:47:50 PM\",\"nautical_twilight_begin\":\"2:40:40 AM\",\"nautical_twilight_end\":\"4:16:36 PM\",\"astronomical_twilight_begin\":\"2:11:47 AM\",\"astronomical_twilight_end\":\"4:45:29 PM\"},\"status\":\"OK\"}

so i write this Simple code: (this is manual write of json code but i want convert auto of webhook recieve data to readable format for library)

BLYNK_WRITE(V0){
  String Data1 = param.asStr();

  Data1.replace('"', 'Q');
  Data1.replace("Q", "\\*");
  Data1.replace('*', '"');

  const char json[] = "{\"results\":{\"sunrise\":\"3:34:07 AM\",\"sunset\":\"3:23:09 PM\",\"solar_noon\":\"9:28:38 AM\",\"day_length\":\"11:49:02\",\"civil_twilight_begin\":\"3:09:26 AM\",\"civil_twilight_end\":\"3:47:50 PM\",\"nautical_twilight_begin\":\"2:40:40 AM\",\"nautical_twilight_end\":\"4:16:36 PM\",\"astronomical_twilight_begin\":\"2:11:47 AM\",\"astronomical_twilight_end\":\"4:45:29 PM\"},\"status\":\"OK\"}";

  const size_t bufferSize = JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(10) + 512;
  DynamicJsonBuffer jsonBuffer(bufferSize);
  JsonObject& root = jsonBuffer.parseObject(json);

  if (!root.success()) {
    Serial.println("parseObject() failed");
    return;
  }
  JsonObject& results = root["results"];
const char* results_sunrise = results["sunrise"]; // "7:27:02 AM"
const char* results_sunset = results["sunset"]; // "5:05:55 PM"
const char* results_solar_noon = results["solar_noon"]; // "12:16:28 PM"
const char* results_day_length = results["day_length"]; // "9:38:53"
const char* results_civil_twilight_begin = results["civil_twilight_begin"]; // "6:58:14 AM"
const char* results_civil_twilight_end = results["civil_twilight_end"]; // "5:34:43 PM"
const char* results_nautical_twilight_begin = results["nautical_twilight_begin"]; // "6:25:47 AM"
const char* results_nautical_twilight_end = results["nautical_twilight_end"]; // "6:07:10 PM"
const char* results_astronomical_twilight_begin = results["astronomical_twilight_begin"]; // "5:54:14 AM"
const char* results_astronomical_twilight_end = results["astronomical_twilight_end"]; // "6:38:43 PM"
const char* status = root["status"]; // "OK"

Serial.println("");
if(int (status[0])-79 == 0) {
int sunrise_sec = ((results_sunrise[0]-48) * 3600) + ((((results_sunrise[2]-48) *10)+(results_sunrise[3]-48) )*60)+(((results_sunrise[5]-48)*10)+(results_sunrise[6]-48));
    Serial.println(sunrise_sec);
    
int sunset_sec = ((results_sunset[0]-48) * 3600) + ((((results_sunset[2]-48) *10)+(results_sunset[3]-48) )*60)+(((results_sunset[5]-48)*10)+(results_sunset[6]-48));
    sunset_sec = sunset_sec + 43200;
    Serial.println(sunset_sec);
    
int solar_noon_sec = ((((results_solar_noon[0]-48)*10)+(results_solar_noon[1]-48))*3600) + ((((results_solar_noon[3]-48) *10)+(results_solar_noon[4]-48) )*60)+(((results_solar_noon[6]-48)*10)+(results_solar_noon[7]-48));
    Serial.println(solar_noon_sec);
    //PM Calculate
    int H = (((results_solar_noon[0]-48)*10)+(results_solar_noon[1]-48));
    if(int (results_sunrise[8]) == 80 && H <= 9) {
      solar_noon_sec = solar_noon_sec + 43200;
    }
    
int day_length_sec = ((results_day_length[0]-48) * 3600) + ((((results_day_length[2]-48) *10)+(results_day_length[3]-48) )*60)+(((results_day_length[5]-48)*10)+(results_day_length[6]-48));
    Serial.println(day_length_sec);
        
int civil_twilight_begin_sec = ((results_civil_twilight_begin[0]-48) * 3600) + ((((results_civil_twilight_begin[2]-48) *10)+(results_civil_twilight_begin[3]-48) )*60)+(((results_civil_twilight_begin[5]-48)*10)+(results_civil_twilight_begin[6]-48));
    Serial.println(civil_twilight_begin_sec);
        
int civil_twilight_end_sec = ((results_civil_twilight_end[0]-48) * 3600) + ((((results_civil_twilight_end[2]-48) *10)+(results_civil_twilight_end[3]-48) )*60)+(((results_civil_twilight_end[5]-48)*10)+(results_civil_twilight_end[6]-48));
    civil_twilight_end_sec = civil_twilight_end_sec + 43200;
    Serial.println(civil_twilight_end_sec);
        
int nautical_twilight_begin_sec = ((results_nautical_twilight_begin[0]-48) * 3600) + ((((results_nautical_twilight_begin[2]-48) *10)+(results_nautical_twilight_begin[3]-48) )*60)+(((results_nautical_twilight_begin[5]-48)*10)+(results_nautical_twilight_begin[6]-48));
    Serial.println(nautical_twilight_begin_sec);
        
int nautical_twilight_end_sec = ((results_nautical_twilight_end[0]-48) * 3600) + ((((results_nautical_twilight_end[2]-48) *10)+(results_nautical_twilight_end[3]-48) )*60)+(((results_nautical_twilight_end[5]-48)*10)+(results_nautical_twilight_end[6]-48));
    nautical_twilight_end_sec = nautical_twilight_end_sec + 43200;
    Serial.println(nautical_twilight_end_sec);
        
int astronomical_twilight_begin_sec = ((results_astronomical_twilight_begin[0]-48) * 3600) + ((((results_astronomical_twilight_begin[2]-48) *10)+(results_astronomical_twilight_begin[3]-48) )*60)+(((results_astronomical_twilight_begin[5]-48)*10)+(results_astronomical_twilight_begin[6]-48));
    Serial.println(astronomical_twilight_begin_sec);
        
int astronomical_twilight_end_sec = ((results_astronomical_twilight_end[0]-48) * 3600) + ((((results_astronomical_twilight_end[2]-48) *10)+(results_astronomical_twilight_end[3]-48) )*60)+(((results_astronomical_twilight_end[5]-48)*10)+(results_astronomical_twilight_end[6]-48));
    astronomical_twilight_end_sec = astronomical_twilight_end_sec + 43200;
    Serial.println(astronomical_twilight_end_sec);
}
else {
  Serial.println("if not passed. please check the if ");
  Serial.println(int (status));
  Serial.println(int (status[0]));
}
}

i success to create :
CPP {\"results\":{\"sunrise\":\"3:34:07 AM\",\"sunset\":\"3:23:09 PM\",\"solar_noon\":\"9:28:38 AM\",\"day_length\":\"11:49:02\",\"civil_twilight_begin\":\"3:09:26 AM\",\"civil_twilight_end\":\"3:47:50 PM\",\"nautical_twilight_begin\":\"2:40:40 AM\",\"nautical_twilight_end\":\"4:16:36 PM\",\"astronomical_twilight_begin\":\"2:11:47 AM\",\"astronomical_twilight_end\":\"4:45:29 PM\"},\"status\":\"OK\"}
From:

{"results":{"sunrise":"6:19:31 AM","sunset":"5:50:31 PM","solar_noon":"12:05:01 PM","day_length":"11:31:00","civil_twilight_begin":"5:53:42 AM","civil_twilight_end":"6:16:20 PM","nautical_twilight_begin":"5:23:45 AM","nautical_twilight_end":"6:46:17 PM","astronomical_twilight_begin":"4:53:44 AM","astronomical_twilight_end":"7:16:17 PM"},"status":"OK"}

But How to use it for library and set it as : But it doesn’t work

  const char json[] = Data1;  // doesn't work

hi!

i do not know, but can’t you do the same, using time input widget?
there is sunrise / sunset option… it is more simpler.

1 Like

problem is set " Data1 " (char) in my code as json for decoding with library. i do not problem with set command line for user.

Doesn’t that require you, the developer, to provide the required software code?

1 Like

Are you using the Webhook widget or you own code to obtain the json stream?

1 Like

i use webhook widget

i thought that he want’s to write code from scratch to acquire sunrise / sunset data.

1 Like

@s.d.engineering work your way through this that I just knocked up for you :slight_smile:

/* GetSunriseV1.ino Blynkified by Costas 28 May 2017
based on Sample Arduino Json Web Client original Copyright Benoit Blanchon 2014-2016
MIT License Arduino JSON library https://github.com/bblanchon/ArduinoJson 

from https://stackoverflow.com/questions/39742067/arduino-json-parser-failing-to-parse-a-uri
 */

#define BLYNK_MAX_READBYTES 512     // can be around 360, needed for Webhook widget
#define DevicePin 2                 // ESP LED, device is active LOW 
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <ArduinoJson.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
#include <Time.h>

WidgetRTC rtc;                    
BlynkTimer timer;
WiFiClient client;


char auth[] =         "xxxx";  
char ssid[] =          "xxxx";
char pass[] =         "xxxx";
char blynkserver[] =   "blynk-cloud.com";  

float timezoneAdj   = 3;                  // needs to be float e.g -14.5
char ClockTimeSecs[9];                    // Char Array to hold current time WITH seconds for display purposes
bool gotData = false;                     // for initial collection of sunrise / sunset times 
char sunrise[12];         
char  sunset[12]; 
unsigned int Secstoday;                   // seconds from midnight to sunrise / sunset
unsigned int NowSeconds;                  // current seconds passed midnight 
unsigned int sunriseSeconds = Secstoday;  // secs since midnight to sunrise
unsigned int sunsetSeconds  = Secstoday;  // secs since midnight to sunset
bool deviceON = false;                    // true ON, false OFF  default OFF for testing will go ON if "evening to dawn" and OFF if "daytime"
float latitude  = 31.2345678;             // TODO consider double not float
float longitude = 20.1234567;             // TODO consider double not float 
bool longEntered = true;                  // used for longitude and latitude entry in Terminal widget 
unsigned int GetPressed = 0;              // When V13 GET button is pressed use WiFiClient to get data not Webhook
unsigned int ApiPressed = 0;              // When V17 API button is pressed use Webhok to get data not WiFiClient
long ProcessStartTime;                    // millis() counter for data processing time
bool isFirstConnect = true;               // to fix RTC not syncing on reboot

const char* server =    "api.sunrise-sunset.org";                         // server's address
char resource[60];                        // WAS   /json?lat=25.044800&lng=43.977615&date=today"; 
int ilatitude =  35;                      // integer variable for latitude
int ilongitude = 33;                      // integer variable for longitude
int ilatrest  = 44800;                    // should be 044800, decimal part of latitude
int ilongrest = 977615;                   // decimal part of longitude
const unsigned long HTTP_TIMEOUT = 3000;  // max respone time from server
const size_t MAX_CONTENT_SIZE = 512;      // max size of the HTTP response  

void setup() {
  //setSyncInterval(1);                     // try sync RTC every second until time is received
  
  pinMode(DevicePin, OUTPUT);             // define DevicePin as an output pin (test with onboard LED)
  digitalWrite(DevicePin, HIGH);          // test with device OFF at reboot
  
  Serial.begin(115200);
  Serial.println(F("\nStarted"));
  Blynk.begin(auth, ssid, pass, blynkserver);
  Blynk.syncVirtual(V19);  // retrieve longitude value from server
  Blynk.syncVirtual(V18);  // retrieve latitude  value from server   
  Serial.println(("Project started"));
  rtc.begin();             // moved to BLYNK_CONNECTED following introduction of APP_CONNECTED function
  timer.setInterval(1000L, checkTime);    // update time every second 
  Blynk.virtualWrite(V20, "\n\n\n\n\nEnter your longitude\n");
  // note the 0 hack for 25.044800 latitude
  sprintf(resource, "/json?lat=%i.0%i&lng=%i.%i&date=today", ilatitude, ilatrest, ilongitude, ilongrest);   // do in setup() and beyond  
  //Serial.println(resource);                
 }

void loop() {
  if(Blynk.connected()){
    Blynk.run();
    //rtc.begin();
  }
  timer.run(); 
}

//
BLYNK_APP_CONNECTED() {                     // This is called when Smartphone App is opened
  Serial.println(F("App Connected."));      // not currently working TODO 
  Blynk.notify("Blynk app just started OK");// send PUSH message each time Blynk app is started
}

BLYNK_APP_DISCONNECTED() {                  // This is called when Smartphone App is closed
  Serial.println(F("App Disconnected."));   // not currently working TODO 
  Blynk.notify("Blynk app just stopped");   // send PUSH message each time Blynk app is stopped
}
//

/******************************************************************************************************/
/*
BLYNK_CONNECTED() {  // see how it's used in TrackioT.ino sketch
  if (isFirstConnect) {
    setSyncInterval(1); // try sync RTC every second until time is received
    Serial.println(F("RTC begins now"));
    //isFirstConnect = false;
    //rtc.begin();           // moved from setup() following introduction of APP_CONNECTED function
  }
}  
*/
/******************************************************************************************************/


void checkTime(){                           // check for rollover of day and get data again
  //Serial.println("107");
  /*if(year() == 1970 && millis() > 24000 & millis() < 25000){ // start RTC 24 to 25s after ESP reboot
    setSyncInterval(1); // try sync RTC every second until time is received from server
    //rtc.begin();
    Serial.println("Trying to sync RTC ........");
  }*/
  if(year() != 1970){                       // time has updated from Blynk server
    sprintf(ClockTimeSecs, "%02d:%02d:%02d", hour(), minute(), second());   // time with seconds
    NowSeconds = (hour() * 3600) + (minute() * 60) + second(); // now seconds passed midnight
    Blynk.virtualWrite(V12, ClockTimeSecs); // display clock time in app 
    if(!gotData){
      ProcessStartTime = millis();          // record start time for data gathering
      if(GetPressed){
        GetPressed = 0;                     // clear the flag
        getSunrise();                       // call getSunrise only via GET button        
      }
      else{
        ApiPressed = 0;                     // clear the flag
        clear4displays(); 
        Blynk.virtualWrite(V18, String(latitude, 8) );
        Blynk.virtualWrite(V19, String(longitude, 8));            
        Blynk.virtualWrite(V2, String(latitude, 8), String(longitude, 8) );  // TODO think String only gives 6dp AND reinstate the line
      }
      gotData = true;  
    }
  
    //if((hour() == 12) && (minute() == 13) && (second() < 3) && (gotData)){   // test only
    if((hour() == 0) && (minute() == 0) && (second() < 3) && (gotData)){   // day has rolled over, will only happen once a day 
      gotData = false;     // used to call data again
    }
    if((NowSeconds >= sunriseSeconds) && (NowSeconds < sunsetSeconds) && (deviceON == true)){
      digitalWrite(DevicePin, HIGH);   // turn OFF device (active LOW)
      deviceON = false; 
      Serial.print(F("Device turned OFF at "));
      Serial.println(ClockTimeSecs);
      Blynk.virtualWrite(V16, "Device turned OFF");
      Blynk.virtualWrite(V20, "\nDevice turned OFF at " + String(ClockTimeSecs) + "\n");      
    }
    if((NowSeconds >= sunsetSeconds) && (hour() < 24) && (deviceON == false)){   // i.e. before midnight check rollover?
      digitalWrite(DevicePin, LOW);    // turn ON device (active LOW) 
      deviceON = true; 
      Serial.print(F("Device turned ON at "));
      Serial.println(ClockTimeSecs);
      Blynk.virtualWrite(V16, "Device turned ON ");
      Blynk.virtualWrite(V20, "\nDevice turned ON  at " + String(ClockTimeSecs) + "\n"); 
    }
    if((NowSeconds < sunriseSeconds) && (deviceON == false)){   // i.e. before sunrise check rollover?
      digitalWrite(DevicePin, LOW);    // turn ON device (active LOW) 
      deviceON = true; 
      Serial.print(F("Device turned ON at "));
      Serial.println(ClockTimeSecs);
      Blynk.virtualWrite(V16, "Device turned ON ");
      Blynk.virtualWrite(V20, "\nDevice turned ON  at " + String(ClockTimeSecs) + "\n"); 
    } 
  }
}

void displaySeconds(){
  timefromArray(sunrise);               // convert array to time
  Serial.print(F("Sunrises "));
  Serial.print(Secstoday);
  Serial.println(F(" seconds after midnight today"));
  Blynk.virtualWrite(V14, Secstoday);
  sunriseSeconds = Secstoday; 
  timefromArray(sunset); 
  Serial.print(F("Sunsets  "));
  Serial.print(Secstoday);
  Serial.println(F(" seconds after midnight today")); 
  Blynk.virtualWrite(V15, Secstoday);
  sunsetSeconds = Secstoday;   
}

void getSunrise(){
  if (connect(server)) {
      clear4displays();
      if (sendRequest(server, resource) && skipResponseHeaders()) {
       char response[MAX_CONTENT_SIZE];
       readReponseContent(response, sizeof(response));      
       parseUserData(response);
      }
  disconnect();
  }  
}

void clear4displays(){
  Blynk.virtualWrite(V10, "---------"); 
  Blynk.virtualWrite(V11, "---------"); 
  Blynk.virtualWrite(V14, "---------"); 
  Blynk.virtualWrite(V15, "---------");      
}

bool connect(const char* hostName) {   // Open connection to the HTTP server
  Serial.print(F("Connecting to "));
  Serial.println(hostName);
  bool ok = client.connect(hostName, 80);
  Serial.print(ok ? "Connected to Sunrise server at " : "Connection Failed at ");
  Serial.println(ClockTimeSecs);
  return ok;
}

bool sendRequest(const char* host, const char* resource) {    // Send the HTTP GET request to the server
  //Serial.print("GET ");           // TODO remove // if you want to see in Serial Monitor
  //Serial.println(resource);       // TODO remove // if you want to see in Serial Monitor
  client.print("GET ");
  client.print(resource);
  //client.println(" HTTP/1.1");
  client.println(" HTTP/1.0");      // needs to be 1.0 not 1.1
  client.print("Host: ");
  client.println(server);
  client.println("Connection: close");
  client.println();
  return true;
}

bool skipResponseHeaders() {                     // Skip HTTP headers so that we are at the beginning of the response's body
  // HTTP headers end with an empty line
  char endOfHeaders[] = "\r\n\r\n";
  client.setTimeout(HTTP_TIMEOUT);
  bool ok = client.find(endOfHeaders); 
  if (!ok) {
   Serial.println(F("No response or invalid response!"));
  }
  return ok;
}

void readReponseContent(char* content, size_t maxSize) {  // Read the body of the response from the HTTP server
  size_t length = client.readBytes(content, maxSize);
  content[length] = 0;
  Serial.println(content);  // TODO remove // if you want to see in Serial Monitor
}

bool parseUserData(char* content) {     // parse & print received data  
  // Compute optimal size of the JSON buffer according to what we need to parse.
  // This is only required if you use StaticJsonBuffer.
  const size_t BUFFER_SIZE =
    JSON_OBJECT_SIZE(2)     // the root object has 2 elements
    + JSON_OBJECT_SIZE(10);   // the "result" object has 10 elements    
  // Allocate a temporary memory pool on the stack
  StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
  // If the memory pool is too big for the stack, use DynamicJsonBuffer jsonBuffer;
  
  JsonObject& root = jsonBuffer.parseObject(content);
   if (!root.success()) {
    Serial.println("JSON parsing failed!");
    return false;
   }
   // It's not mandatory to make a copy, you could just use the pointers
   // Since, they are pointing inside the "content" buffer, make sure it's still in memory when you read the string    
   JsonObject& results = root["results"];
   strcpy(sunrise, results["sunrise"]);  // "2:32:19 AM"
   strcpy(sunset,  results["sunset"]);   // "4:50:35 PM"
   Serial.print(F("Sunrise = "));
   Serial.print(sunrise);
   Serial.println(F(" UTC, not local time"));
   Serial.print(F("Sunset  = "));
   Serial.print(sunset);
   Serial.println(F(" UTC, not local time"));
   Blynk.virtualWrite(V10, sunrise);     // TODO sometimes only showing 3dp with V13 (WiFi Client) button
   Blynk.virtualWrite(V11, sunset);      // TODO sometimes only showing 3dp with V13 (WiFi Client) button
   displaySeconds();                     // display seconds from midnight for sunrise / sunset 
   Serial.print(F("Processing time "));
   Serial.print(millis() - ProcessStartTime);
   Serial.println(F(" milliseconds"));  
  return true;
}

void disconnect() {    // Close the connection with the HTTP server
  Serial.println(F("Disconnected from Sunrise server"));
  client.stop();
}

/********** function to convert api time into seconds since midnight with local timezone adjustment **********************/

int timefromArray(char* sunriseset){   // https://sunrise-sunset.org/api formats minutes and seconds with 2 digits (GOOD)
  // https://api.sunrise-sunset.org/json?lat=25.044800&lng=43.977615&date=today 
  /* 28/5/17 is {"results":{"sunrise":"2:32:19 AM","sunset":"4:50:35 PM","solar_noon":"9:41:27 AM","day_length":"14:18:16",
  "civil_twilight_begin":"2:03:22 AM","civil_twilight_end":"5:19:31 PM","nautical_twilight_begin":"1:27:45 AM",
  "nautical_twilight_end":"5:55:08 PM","astronomical_twilight_begin":"12:48:56 AM","astronomical_twilight_end":"6:33:58 PM"},"status":"OK"} 
  Sunrise 19939 seconds local time
  Sunset  71435 seconds local time
  */
  unsigned int riseHours;
  unsigned int riseMinutes;
  unsigned int riseSeconds;
  bool PMtime = false;
  float timezoneAdj   = 3.00;  // needs to be float e.g -14.50 for minus 14 and a half hours behind UTC 
  char * p; 
  const char* lookfor = "AM";
  p = strstr (sunriseset, lookfor);  // search for first occurence of lookfor (AM) in sunrise
  if((int) (p - sunriseset) > 0){    // must be this way as p is a pointer
    PMtime = false; 
  }
  else{
    PMtime = true;
  } 
  riseHours = atoi(&sunriseset[0]);
  unsigned int x = 0;
  if(String(strlen(sunriseset))== "10"){  // value is a string not an int
    x = 1;
  }  
  riseMinutes = atoi(&sunriseset[3 - x]);
  riseSeconds = atoi(&sunriseset[6 - x]);
  Secstoday = (riseHours * 3600) + (riseMinutes * 60) + riseSeconds; 
  if(PMtime){                         // if PM, add 12 hours x 60 minutes x 60 seconds = 43200 seconds
    Secstoday = Secstoday + 43200;  
  }
  Secstoday = Secstoday + (timezoneAdj * 3600);   // timezone adjustment
  return Secstoday;
}

/************************** Blynk widgets *************************************************************/
BLYNK_WRITE(V2){            // Webhook pin for sunrise api
  String webhookdata = param.asStr();
  Serial.println(webhookdata);
  char apiCall[webhookdata.length() + 1];
  webhookdata.toCharArray(apiCall, (webhookdata.length() + 1)); // convert String to Char array
  webhookdata = "";
  parseUserData(apiCall);
  gotData = true; 
}

BLYNK_WRITE(V13){                   // button to call getSunrise() via WiFi Client;
  int LocalGetPressed = param.asInt(); 
  if(LocalGetPressed){
    GetPressed = LocalGetPressed;   // global variable     
    resource[0] = (char)0;          // start to create a new resource for client call by clearing existing char array
    ilatitude = int(latitude + 0.0);         // e.g. 25.1234567 becomes 25 rounding not required
    int tmplat  = latitude * 10000000L;      // e.g. 351234567
    //Serial.println(tmplat);
    int tmplatitude = ilatitude * 10000000L; // e.g. 250000000
    ilatrest = tmplat - tmplatitude;         // e.g.   1234567
    //Serial.println(ilatrest);
    // 0 hack follows e.g. for 23.044800 latitude etc
    if(ilatrest < 1000000){                  // e.g    0123456 only 6 digits not 7 so pad with 0
      sprintf(resource, "/json?lat=%i.0%i&lng=", ilatitude, ilatrest); // padded decimals with 0 for latitude
    }
    else{
      sprintf(resource, "/json?lat=%i.%i&lng=", ilatitude, ilatrest);   // no decimal padding required for latitude
    }
    ilongitude = int(longitude + 0.0);         // e.g. 25.1234567 becomes 25 rounding not required
    int tmplong  = longitude * 10000000L;      // e.g. 351234567
    //Serial.println(tmplong);
    int tmplongitude = ilongitude * 10000000L; // e.g. 350000000
    ilongrest = tmplong - tmplongitude;        // e.g.   1234567
    //Serial.println(ilongrest);
    // 0 hack follows e.g. for 23.044800 longitude etc 
    if(ilongrest < 1000000){                  // e.g    0123456 only 6 digits not 7 so pad with 0
      sprintf(resource, "%s%i.0%i&date=today", resource, ilongitude, ilongrest); // padded decimals with 0 for longitude
    }
    else{
      sprintf(resource, "%s%i.%i&date=today", resource, ilongitude, ilongrest);   // no decimal padding required for longitude
    }
    Serial.println(resource);       // 0 padding adds a 7th decimal place but it's only a few mm
    gotData = false;                // reset flag
    checkTime();                    // this will call getSunrise();
  }
}

BLYNK_WRITE(V17){                   // button to call Webhook API
  int LocalApiPressed = param.asInt();
  if(LocalApiPressed){
    ApiPressed = LocalApiPressed;   // global variable
    gotData = false;                // reset flag     
  } 
}

BLYNK_WRITE(V18){                   // display widget for latitude,  sync on ESP restart
  latitude = param.asFloat();
  //Serial.println(latitude, 7);  
}

BLYNK_WRITE(V19){                   // display widget for longitude, sync on ESP restart
  longitude = param.asFloat();
  //Serial.println(longitude, 7);  
}

BLYNK_WRITE(V20){                                             // Terminal widget to enter longitude and latitude
  String terminalString = param.asStr();                      
  if(longEntered == true){
    Blynk.virtualWrite(V20, "\n\n\n\n\nEnter your latitude\n");
    longitude = terminalString.toFloat();                     // convert String to float
    Serial.println(longitude, 7);    
    Blynk.virtualWrite(V19, String(longitude, 8));
    longEntered = false;
  }
  else{
    Blynk.virtualWrite(V20, "\n\n\n\n\nEnter your longitude\n"); 
    latitude = terminalString.toFloat();                       // convert String to float
    Serial.println(latitude, 7);
    Blynk.virtualWrite(V18, String(latitude, 8));
    longEntered = true;     
  }
} 
2 Likes

Actually I was having a tidy up yesterday following the new cloning procedure (no server to server facility) and I this is the new version QR code for the project on Blynk’s server. It will not work on a local server.

Revised QR code and Smartphone url (ANDROID ONLY) http://tinyurl.com/y7a9v7wf

Energy required 3300 units.

1 Like

The Qr Code is not Valid

Are you on iOS? IOS app update with support for new clonning wasn’t released yet.

@Eugene I’m on Android what about you @s.d.engineering ?

Screenshot and new QR to follow asap if you confirm you are using Android.

Note some items are UTC and some are local times.

There are 4 widgets off the bottom of the screen:
'1. Email widget
'2. Webhook widget on V2 with label LatLong and the following url:

https://api.sunrise-sunset.org/json?lat=/pin[0]/&lng=/pin[1]/&date=today

'3. RTC set to local time
'4 Notification widget:
ON
5 sec
High priority
Ringtone - whatever you want

1 Like

yes i’m on iOS

@s.d.engineering I have updated the QR code above because yesterday as soon as I cloned the project I then deleted the project. This was probably OK with the old cloning system but not the new one. So I have recreated it on the Blynk server from a copy on my own cloud server. Will not be any good to you though as an iOS user.

This might help, along with the notes in my previous post. Also I have SEND APP CONNECTED COMMAND set to ON in the main project settings. All widgets set as PUSH frequency.

1 Like

@Costas very useful so many Thanks.
:pray:

so another question is how can i store The sunrise or The sunset (milis) on memory of my ESP?
cause i want to use those when i can’t access to internet and API Server to receive new Times (after reset device and next boot it doesn’t need to access again to internet and API Service).

another way how can i store a integer value on memory that it doesn’t clear after reset The ESP?

You can use SPIFFS or the ESP’s equivalent of EEPROM.

1 Like

Are you have any source for download (i.e. example 10 years of The Sunrise or … )?
or how can i access to The sunrise for 10 or any years of sun ibo

I don’t have the data but Google will have it.
Do you just need the data for a single location or for all longitude / latitudes?

1 Like

i want it just for a single location.