最初はプレゼントタイマーを作るつもり。
しかし、TinyebDBの文字列を表示する方がはるかも簡単、汎用性もいい。
できたものはこれ:

電源が繋いたら、WiFiを自動で接続、それからTinyWebDBから文字列を取得と表示する。
これならプレゼントタイマーだけじゃなく、お知らせ、顔認証して名前で挨拶とかにも活用できそう。
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Max72xxPanel.h>
#include <time.h>
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
WiFiClient client;
const char* resource = "http://tinydb.ml/api/"; // http resource
const unsigned long BAUD_RATE = 9600; // serial connection speed
const unsigned long HTTP_TIMEOUT = 10000; // max respone time from server
const size_t MAX_CONTENT_SIZE = 512; // max size of the HTTP response
#include "WiFiManager.h" //https://github.com/tzapu/WiFiManager
HTTPClient http;
int pinCS = D4; // Attach CS to this pin, DIN to MOSI and CLK to SCK (cf http://arduino.cc/en/Reference/SPI )
int numberOfHorizontalDisplays = 4;
int numberOfVerticalDisplays = 1;
char time_value[20];
// LED Matrix Pin -> ESP8266 Pin
// Vcc -> 3v (3V on NodeMCU 3V3 on WEMOS)
// Gnd -> Gnd (G on NodeMCU)
// DIN -> D7 (Same Pin for WEMOS)
// CS -> D4 (Same Pin for WEMOS)
// CLK -> D5 (Same Pin for WEMOS)
Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
int wait = 70; // In milliseconds
int spacer = 1;
int width = 5 + spacer; // The font width is 5 pixels
void configModeCallback (WiFiManager *myWiFiManager) {
Serial.println("Entered config mode");
Serial.println(WiFi.softAPIP());
//if you used auto generated SSID, print it
display_message(myWiFiManager->getConfigPortalSSID());
}
void setup() {
configTime(0 * 3600, 0, "pool.ntp.org", "time.nist.gov");
matrix.setIntensity(10); // Use a value between 0 and 15 for brightness
matrix.setRotation(0, 1); // The first display is position upside down
matrix.setRotation(1, 1); // The first display is position upside down
matrix.setRotation(2, 1); // The first display is position upside down
matrix.setRotation(3, 1); // The first display is position upside down
display_message("wifiManager autoConnect...");
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;
//reset settings - for testing
//wifiManager.resetSettings();
//set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
wifiManager.setAPCallback(configModeCallback);
//fetches ssid and pass and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
if(!wifiManager.autoConnect()) {
Serial.println("failed to connect and hit timeout");
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(1000);
}
//if you get here you have connected to the WiFi
Serial.println("connected...yeey :)");
}
void loop() {
matrix.fillScreen(LOW);
get_TinyWebDB("presentationtimer");
delay(1000);
}
void display_message(String message) {
if (message.length() > 5) scrool_message(message);
else {
for ( int i = 0 ; i < message.length(); i++ ) {
matrix.drawChar(2 + i * width, 0, message[i], HIGH, LOW, 1); //
}
matrix.write(); // Send bitmap to display
}
}
void scrool_message(String message) {
for ( int i = 0 ; i < width * message.length() + matrix.width() - spacer; i++ ) {
//matrix.fillScreen(LOW);
int letter = i / width;
int x = (matrix.width() - 1) - i % width;
int y = (matrix.height() - 8) / 2; // center the text vertically
while ( x + width - spacer >= 0 && letter >= 0 ) {
if ( letter < message.length() ) {
matrix.drawChar(x, y, message[letter], HIGH, LOW, 1); // HIGH LOW means foreground ON, background off, reverse to invert the image
}
letter--;
x -= width;
}
matrix.write(); // Send bitmap to display
delay(wait / 2);
}
}
void get_TinyWebDB(const char* tag) {
int httpCode;
char tag2[32];
char value[128];
httpCode = TinyWebDBGetValue(tag);
// httpCode will be negative on error
if(httpCode > 0) {
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
if(httpCode == HTTP_CODE_OK) {
String payload = http.getString();
Serial.println(payload);
const char * msg = payload.c_str();
if (TinyWebDBreadReponseContent(tag2, value, msg)){
TinyWebDBGotValue(tag2, value);
}
}
} else {
Serial.printf("[HTTP] POST... failed, error: %s\n", http.errorToString(httpCode).c_str());
TinyWebDBWebServiceError(http.errorToString(httpCode).c_str());
}
http.end();
delay(1000);
}
// Parse the JSON from the input string and extract the interesting values
// Here is the JSON we need to parse
// [
// "VALUE",
// "LED1",
// "on",
// ]
bool TinyWebDBreadReponseContent(char* tag, char* value, const char* payload) {
// Compute optimal size of the JSON buffer according to what we need to parse.
// See https://bblanchon.github.io/ArduinoJson/assistant/
const size_t BUFFER_SIZE =
JSON_OBJECT_SIZE(3) // the root object has 3 elements
+ MAX_CONTENT_SIZE; // additional space for strings
// Allocate a temporary memory pool
DynamicJsonBuffer jsonBuffer(BUFFER_SIZE);
// JsonObject& root = jsonBuffer.parseObject(payload);
JsonArray& root = jsonBuffer.parseArray(payload);
JsonArray& root_ = root;
if (!root.success()) {
Serial.println("JSON parsing failed!");
return false;
}
// Here were copy the strings we're interested in
strcpy(tag, root_[1]); // "led1"
strcpy(value, root_[2]); // "on"
return true;
}
int TinyWebDBWebServiceError(const char* message)
{
}
// ----------------------------------------------------------------------------------------
// Wp TinyWebDB API
// Action URL Post Parameters Response
// Get Value {ServiceURL}/getvalue tag JSON: ["VALUE","{tag}", {value}]
// ----------------------------------------------------------------------------------------
int TinyWebDBGetValue(const char* tag)
{
char url[64];
sprintf(url, "%s%s?tag=%s", resource, "getvalue/", tag);
Serial.printf("[HTTP] %s\n", url);
// configure targed server and url
http.begin(url);
Serial.print("[HTTP] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();
return httpCode;
}
int TinyWebDBGotValue(const char* tag, const char* value)
{
Serial.printf("[TinyWebDB] %s\n", tag);
Serial.printf("[TinyWebDB] %s\n", value);
display_message(value);
delay(1000);
display_message(value);
return 0;
}
TinyWebDBに文字列を用意方法はいくつもある。
- HTMLフォームで送信
- App Inventor で簡単なアプリ開発
- cURLで送信
- TinyWebDBサイトを直接いじる。
<h1>TinyWebDB test program</h1>
<form action="http://tinydb.ml/api/storeavalue" method="post">
<div>tag: <input type="text" name="tag" value="presentationtimer"></div>
<div>value: <input type="text" name="value" value="12:13"></div>
<input type="submit" value="submit">
<input type="reset" value="reset">
</form>