Here is a rapid prototype app I just put together which might be of interest to some people.
Basically, I have parsed the data from a Chinese web site which is tracking the Wuhan coronavirus, and cache that data every minute via a local cron file and make a simple API available to a Blink app. I have not had time to DEBUG why the ArduinoJSON lib did not work (yet) for me; so my apologies for this simple string-based API and crude parsing method. However, the app, as written, does work.
If you live in an infected area in China and would like to use this app but you do not have time to build the Blynk app yourself due to the ongoing crisis in your area, please contact me in this thread (or by private email or message) and I will share this app with you at my expense (around $1 to $2 per person, up to 200 people).
Please note you do not need to run the Arduino code on an ESP8266. You can simple run the Blynk app on your mobile phone. The ESP8266 device I am running will update this Blynk app automatically. However, if you run your own Blynk app, of course that will cost me less "Blynk energy credits" (I wish Blynk would just credit me a few hundred thousand "energy credits" so I could build and provide more free public service apps during times of crisis).
Also, please reply in this discussion and with any suggestions you might have to improve this "rapid response" app, including any APIs (with relevant, credible data) you may know about. If enough people are interested, and find this helpful, I may add time-series graphs to the app.
Also, if anyone wants to improve the code below to get ArduinoJSON to work, that would be great. Then we could replace the crude parser I quickly hacked together to get this out quickly.
Hope this helps someone.
The resulting Blynk app looks like this:
Here is the ESP8266 Arduino Code. Feel free to use the API I created (in the code):
/
*************************************************************
Simple Blynk App for the Wuhan Virus (Version 0.1)
Data from a key Chinese web site which publishes these stats.
This is the same Chinese web page used by The Johns Hopkins University and others.
You may use the code as you find useful, including the API from unix.com as a public service during this crisis.
Neo: The UNIX and Linux Forums - Free Tech Support 1 February 2020
*************************************************************/
/* Comment this out to disable prints and save space */
#define BLYNK_PRINT Serial
#define DEBUG false
#include <SPI.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <WiFiClientSecure.h>
#include <ESP8266HTTPClient.h>
BlynkTimer timer;
// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "YOUR_BLYNK_AUTHORIZATION_TOKEN";
// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "YOUR_WIFI_SSID";
char pass[] = "YOUR_WIFI_PASSWORD";
const char *host = "www.unix.com";
const int httpsPort = 443; //HTTPS= 443 and HTTP = 80
//The SHA1 finger print of The UNIX and Linux Forums - Free Tech Support SSL certificate
const char fingerprint[] PROGMEM = "8F 60 34 7B C0 FE CF 3C A8 2B 6D 31 6B 4B 9F C3 5B 6E A0 5F";
void setup()
{
// Debug serial console
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
// 15 seconds init and update interval; you can easily set this to a few minutes, as the data changes slowly
timer.setInterval(15000L, myTimerEvent);
}
void loop()
{
Blynk.run();
timer.run();
}
void myTimerEvent()
{
WiFiClientSecure httpsClient; //Declare object of class WiFiClient
Serial.println(host);
Serial.printf("Using fingerprint '%s'\n", fingerprint);
httpsClient.setFingerprint(fingerprint);
httpsClient.setTimeout(30000); // 30 Seconds
delay(1000);
Serial.print("HTTPS Connecting");
int r = 0; //retry counter
while ((!httpsClient.connect(host, httpsPort)) && (r < 30)) {
delay(100);
Serial.print(".");
r++;
}
if (r == 30) {
Serial.println("Connection failed");
}
else {
Serial.println("Connected to web");
}
String Link;
long rssi = WiFi.RSSI();
String macaddr = WiFi.macAddress();
Serial.print("RSSI:");
Serial.println(rssi);
Serial.print("MAC: ");
Serial.println(macaddr);
// RSSI and MAC are for logging, statistical, and debugging purposes and is not shared with any third part. You can omit RSSI and MAC if you wish, as follows:
//Link = "/wuhan/";
//As for me, I use RSSI and MAC because I like having this kind of data for debugging.
Link = "/wuhan/?rssi=" + String(rssi) + "&mac=" + macaddr;
Serial.print("requesting URL: ");
Serial.println(host + Link);
httpsClient.print(String("GET ") + Link + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
Serial.println("request sent");
while (httpsClient.connected()) {
String line = httpsClient.readStringUntil('\n');
if (line == "\r") {
Serial.println("headers received");
break;
}
}
Serial.println("reply was:");
Serial.println("==========");
String line;
while (httpsClient.available()) {
line = httpsClient.readStringUntil('\n'); //Read Line by Line
Serial.println(line); //Print response
}
Serial.println("==========");
Serial.println("closing connection");
// crude way to parse string - should convert to json later
int ind1 = line.indexOf(':'); //finds location of first :
String confirmed = line.substring(0, ind1); //captures first data String
int ind2 = line.indexOf(':', ind1 + 1 ); //finds location of second :
String suspected = line.substring(ind1 + 1, ind2 + 1); //captures second data String
int ind3 = line.indexOf(':', ind2 + 1 ); //finds location of third :
String recovered = line.substring(ind2 + 1, ind3 + 1);//captures second data String
int ind4 = line.indexOf(':', ind3 + 1 ); //finds location of third :
String deaths = line.substring(ind3 + 1, ind4 + 1);//captures second data String
if (DEBUG) {
Serial.println(String(confirmed)); Serial.println(suspected);; Serial.println(deaths); //Print response
Serial.println(String(recovered));
}
if (confirmed.toInt() > 0) {
confirmed.replace(":", ""); deaths.replace(":", ""); suspected.replace(":", "");
recovered.replace(":", "");
Blynk.virtualWrite(V0, confirmed.toInt());
Blynk.virtualWrite(V1, suspected.toInt());
Blynk.virtualWrite(V2, deaths.toInt());
Blynk.virtualWrite(V3, recovered.toInt());
}
}
Running and updating live from the balcony: