Tuesday, September 27, 2022

Solar K Index display from BOM using ESP32

There is significant solar activity at the moment. This activity changes radio propagation quite a bit for bad and good. One of the measures is called the K Index. I've been having good success with the little TTGO ESP32 + LCD boards and today created some code to fetch and display the K index.


This site has a good explanation which I reproduce here.

The K index is computed once every three hours (eight times a day) and the values can range from 0 to 9, with 0 being inactive, and 9 representing an extreme severe storm condition. The values are quadi-logarithmic.

K = 0 Inactive

K = 1 Very quiet

K = 2 Quiet

K = 3 Unsettled

K = 4 Active

K = 5 Minor storm

K = 6 Major storm

K = 7 Severe storm

K = 8 Very severe storm

K = 9 Extremely severe storm

Also, from here:

"The K-index, and by extension the Planetary K-index, are used to characterize the magnitude of geomagnetic storms. Kp is an excellent indicator of disturbances in the Earth's magnetic field and is used by SWPC to decide whether geomagnetic alerts and warnings need to be issued for users who are affected by these disturbances.

The principal users affected by geomagnetic storms are the electrical power grid, spacecraft operations, users of radio signals that reflect off of or pass through the ionosphere, and observers of the aurora."

To get the current value for Australia, in an easily machine readable form, I turned to our fantastic Space Weather Service of the Bureau of Meteorology. They have an API for this and other data documented here. Note that to use the API you must register with your email address and get an API key to use in requests.

There's not a lot to the code. It is built with the Arduino tool chain and uses the built-in esp32 http library and uses ArduinoJson to extract the figures. 

#include <WiFi.h>

#include <WiFiMulti.h>

#include <HTTPClient.h>

#include <ArduinoJson.h>

#include <ArduinoJson.hpp>

#include <TFT_eSPI.h>

#include <TFT_eWidget.h>

const char *kWifiNetwork = "SSID";

const char *kWifiPassword = "PASSWORD";

const char * API_KEY = "PUT YOUR API KEY HERE";

TFT_eSPI tft = TFT_eSPI();

WiFiMulti wifiMulti;

void setup() {

  Serial.begin(115200);

  while (!Serial) {

    ; // wait for serial port to connect. Needed for native USB port only

  }

  Serial.println("Starting...");

  wifiMulti.addAP(kWifiNetwork, kWifiPassword);

  tft.begin();

  tft.setRotation(3);

  tft.fillScreen(TFT_BLACK);

  tft.drawString("Starting", 10, 10, 4);

}

void loop() {  

// wait for WiFi connection

  if((wifiMulti.run() == WL_CONNECTED)) {

    tft.fillScreen(TFT_BLACK);

    tft.drawString("Connecting", 10, 10, 4);

      HTTPClient http;

      http.begin("https://sws-data.sws.bom.gov.au/api/v1/get-k-index"); //HTTP

      http.addHeader("Content-Type", "application/json");

      String payload = "{\"api_key\": \"" + String(API_KEY) + "\", \"options\": {\"location\": \"Australian region\"}}";

      Serial.println(payload);

      int httpCode = http.POST(payload);

      Serial.println(httpCode);

      // httpCode will be negative on error

      if(httpCode > 0) {

          // HTTP header has been send and Server response header has been handled

          // file found at server

          if(httpCode == HTTP_CODE_OK) {

              String payload = http.getString();

              // https://arduinojson.org

              DynamicJsonDocument doc(1024);

              DeserializationError error = deserializeJson(doc, payload);

              // Test if parsing succeeds.

              if (error) {

                Serial.print(F("deserializeJson() failed: "));

                Serial.println(error.f_str());

                return;

              }

              Serial.println("Deserialised OK");

              Serial.println(payload);              

              long k_index = doc["data"][0]["index"];

              const char*  analysis_time = doc["data"][0]["analysis_time"];

              Serial.printf("K Index = %ld\n", k_index);

              Serial.printf("analysis time = %s\n", analysis_time);

              Serial.println("Serial print OK");

              tft.fillScreen(TFT_BLACK);

              tft.drawString("K Index", 10, 10, 4);

              tft.drawString(String(k_index), 90, 30, 8);

              tft.drawString(analysis_time, 5, 120, 2);

            if (error) {

              Serial.printf("Json error");

            return;

            }


          } else {

            tft.fillScreen(TFT_BLACK);

            tft.drawString("Http error", 10, 10, 4);

            Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());

          }

      http.end();

      }

  }

  delay(200000);

}

It varies during the day and I believe if K hits 5 things start getting serious.




All credit to the good folks at the BOM for making this easy and free to access.

1 comment:

vk3bek said...

I've been wanting to do something similar to this for a while, only instead of a numerical display have some LEDs that replicate the "Normal, Moderate, Severe/Disturbed" indicators at the top of the SWS page with the corresponding colours.