Skip to content

Commit

Permalink
add files
Browse files Browse the repository at this point in the history
  • Loading branch information
ukkz committed Aug 23, 2024
1 parent bd3c34e commit f15443a
Show file tree
Hide file tree
Showing 7 changed files with 554 additions and 2 deletions.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 uko

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
96 changes: 94 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,94 @@
# tiny-key-value-store
A simple key-value store library using generic FS (SD/SPIFFS/FatFS/LittleFS/etc) functions for Arduino family boards.
# Tiny Key Value Store Arduino Library

A simple key-value store library using generic FS (SD/SPIFFS/FatFS/LittleFS/etc) functions for Arduino family boards.

## Getting Started

### Global (sketch beginning) part

#### AVR family boards

Use with SD shield.

```cpp
#include <SPI.h>
#include <SD.h>
#include <TinyKeyValueStore.h>

TinyKeyValueStore store = TinyKeyValueStore(SD);
```

#### ESP8266 / ESP32 boards

Use SPIFFS recommended.

```cpp
#include <SPIFFS.h>
#include <TinyKeyValueStore.h>

TinyKeyValueStore store = TinyKeyValueStore(SPIFFS);
```

Note: Don't forget to set partition scheme setting as `*** with spiffs` before uploading the sketch.

### Common part

```cpp
void setup() {
// 1. Begin based FS class
if (!SD.begin(SS, SPI)) Serial.println("SD Mount Failed");
// please replace above if you use any other FS libraries

// 2. Begin tiny-key-value-store
store.begin("config.txt");

// 3. Read and Write the values associated with the keys
store.set("KEY_NAME", "hello this is VALUE");
String val = store.get("KEY_NAME");

Serial.begin(38400);
Serial.println(val); // hello this is VALUE
}
```

## Dependency

Requires at least one generic FS extended library like SD, SPIFFS, FatFS, LittleFS, Seeed_FS, etc.

## API

### TinyKeyValueStore(fs::FS& fs_obj)

`fs_obj` : SPIFFS / FFat / LittleFS / SD / and ...

### void begin(const char* read_write_filename, const char* read_only_filename = "")

`read_write_filename` : Required. File name for storing key-value data.
`read_only_filename` : Optional. The keys stored in this file are readable, but cannot update value, cannot create additional keys in the sketch.

### String get(const String key)

Get the value as String.

### void getCharArray(const String key, char* charArray)

Get the value as char*.

```cpp
char mes[30];
store.getCharArray("KEY_NAME", mes);
Serial.printf("Message: %s\n", mes); // Message: hello this is VALUE
```

### bool set(const String key, const String value)

Set the value.
Returns true if the value added or updated successfully, otherwise returns false.

### bool setIfFalse(const String key, const String value)

Set the argument as value only if existing value equals to FALSE (or 0, empty string).

## License

This project is licensed under the MIT License - see the LICENSE.md file for details.
94 changes: 94 additions & 0 deletions examples/BasicSerialString/BasicSerialString.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/**
* Tiny Key Value Store
* Basic usage example: storing 2 messages alternatively
* Please open serial monitor and try to send a string message after uploading this sketch
*/

#ifdef ARDUINO_ARCH_ESP32
#include <FS.h>
#include <SPIFFS.h>
#include <FFat.h>
#include <LittleFS.h>
#include <SD.h>
#elif ARDUINO_ARCH_ESP8266
#include <FS.h>
#include <SD.h>
#elif __SEEED_FS__
#include <Seeed_FS.h>
#include <SD/Seeed_SD.h>
#else
#include <SPI.h>
#include <SD.h>
#endif

/* Library */
#include <TinyKeyValueStore.h>
#define MESSAGE_KEY_1 "sample_message_1"
#define MESSAGE_KEY_2 "sample_message_2"
#define STORE_FILE_NAME "/config.txt" // filename must starts with "/"

bool store1or2 = true; // true: 1, false:2

/**
* Choose one FS library as arguments for storing data
* Note: Please check "Tools -> Partition Scheme" settings on ESP32 if happens mount failure
* (when using SPIFFS/FatFS/LittleFS)
*/
TinyKeyValueStore store = TinyKeyValueStore(SPIFFS);
//TinyKeyValueStore store = TinyKeyValueStore(FFat);
//TinyKeyValueStore store = TinyKeyValueStore(LittleFS);
//TinyKeyValueStore store = TinyKeyValueStore(SD);


void setup() {
Serial.begin(38400);

/* first, begin a FS class you chose */
if (!SPIFFS.begin(true)) Serial.println("SPIFFS Mount Failed");
//if (!FFat.begin(true)) Serial.println("FFat Mount Failed");
//if (!LittleFS.begin(true)) Serial.println("LittleFS Mount Failed");
//if (!SD.begin(SS, SPI)) Serial.println("SD Mount Failed"); // replace SS and SPI to appropriate PINs with your board

/* second, begin TinyKeyValueStore after beginning FS class */
store.begin(STORE_FILE_NAME);

/* message1: get as string class */
String sample_message_1 = store.get(MESSAGE_KEY_1);
Serial.print("Stored message 1: "); Serial.println(sample_message_1);
/* message2: get as char* */
char sample_message_2[100];
store.getCharArray(MESSAGE_KEY_2, sample_message_2);
Serial.printf("Stored message 2: %s\n", sample_message_2);

Serial.println("==============================");
Serial.println("Send me something...\n");
}


void loop() {
if (Serial.available() > 0) {
String buf = Serial.readStringUntil('\n');
buf.trim();
Serial.printf("Received \"%s\"", buf.c_str());

/* store as message 1 or 2 */
if (store1or2) {
Serial.println(" -> message 1");
store.set(MESSAGE_KEY_1, buf);
} else {
Serial.println(" -> message 2");
store.set(MESSAGE_KEY_2, buf);
}
store1or2 = !store1or2; // for next

String sample_message_1 = store.get(MESSAGE_KEY_1);
Serial.print("Stored message 1: "); Serial.println(sample_message_1);
char sample_message_2[100];
store.getCharArray(MESSAGE_KEY_2, sample_message_2);
Serial.printf("Stored message 2: %s\n", sample_message_2);

Serial.println("==============================");
Serial.println("Send me something...\n");
}
delay(1);
}
179 changes: 179 additions & 0 deletions examples/WiFiConfig/WiFiConfig.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
/**
* Tiny Key Value Store
* Advanced usage example: Edit WiFi info with your smartphone and keep the configuration
* ================================================================================
* Note: THIS SKETCH IS DESIGNED ONLY FOR M5STACK FAMILY DEVICES WITH DISPLAY
* ================================================================================
* 1. Write this sketch and boot your device
* 2. Please press any button or touch display just after boot up the device to be config mode
* 3. Scan QR code by your smartphone to join the device's wifi access point
* 4. Wait some seconds or following the smartphone's instruction to access the WiFi config page (Captive Portal Web)
* 5. Please input WiFi config information and NTP hostname
* 6. Tap "Update & Reboot" button to reboot your device
* 7. If all information is correct, your device will be connected WiFi and got NTP server time
*/

/* M5 */
#include <M5Unified.h>
#include <FS.h>
#include <SPIFFS.h>
#include <FFat.h>
#include <LittleFS.h>
#include <SD.h>

/* WiFi */
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <WebServer.h>
#include <WiFiAP.h>
#include <DNSServer.h>
WiFiClientSecure client;

/* Library */
#include <TinyKeyValueStore.h>
#define STORE_FILE_NAME "/config.txt" // filename must starts with "/"

/* Keys & Default values */
#define KEY_WIFI_SSID "wifi_ssid"
#define KEY_WIFI_PSWD "wifi_passwd"
#define KEY_NTPD_HOST "ntp_host"
char ssid[64];
char pswd[64];
char host[128];

/* Mode flag (Normal or Config) */
bool config_mode = false;
/* Config Web page HTML */
const char* config_html_template =
#include "config.html.h"
;
String configHTML = String(""); // create later from template with some vars
/* Config Web Server */
const char* config_ssid = "TinyKeyValueStoreDevice";
WebServer configServer(80);
const byte DNS_PORT = 53;
IPAddress dnsIP(8, 8, 4, 4);
DNSServer dnsServer;

/**
* Choose one FS library as arguments for storing data
* Note: Please check "Tools -> Partition Scheme" settings on ESP32 if happens mount failure
* (when using SPIFFS/FatFS/LittleFS)
*/
TinyKeyValueStore store = TinyKeyValueStore(SPIFFS);
//TinyKeyValueStore store = TinyKeyValueStore(FFat);
//TinyKeyValueStore store = TinyKeyValueStore(LittleFS);
//TinyKeyValueStore store = TinyKeyValueStore(SD);

/* Reading config vars and create HTML */
void configLoad(bool updated = false) {
store.getCharArray(KEY_WIFI_SSID, ssid);
store.getCharArray(KEY_WIFI_PSWD, pswd);
store.getCharArray(KEY_NTPD_HOST, host);
char buf[3000];
const char* updated_notice = updated ? "Updated" : "";
sprintf(buf, config_html_template, updated_notice, ssid, pswd, host);
configHTML = String(buf);
}

/* Handler function for accessing the config web server */
void configWeb() {
if (configServer.method() == HTTP_POST) {
/* POST access: updating vars */
if (configServer.arg(KEY_WIFI_SSID).length() != 0) store.set(KEY_WIFI_SSID, configServer.arg(KEY_WIFI_SSID));
if (configServer.arg(KEY_WIFI_PSWD).length() != 0) store.set(KEY_WIFI_PSWD, configServer.arg(KEY_WIFI_PSWD));
if (configServer.arg(KEY_NTPD_HOST).length() != 0) store.set(KEY_NTPD_HOST, configServer.arg(KEY_NTPD_HOST));
if (configServer.arg("reboot").equals("yes")) ESP.restart(); // when reboot button clicked
configLoad(true); // updated
} else {
/* GET access: only show current config values */
configLoad(false); // not updated
}
configServer.send(200, "text/html", configHTML);
}

void setup() {
auto cfg = M5.config();
M5.begin(cfg);
M5.Display.setTextColor(0xFFFFFFU, 0x000000U);
M5.Display.setTextFont(2);

/* first, begin a FS class you chose */
if (!SPIFFS.begin(true)) Serial.println("SPIFFS Mount Failed");
//if (!FFat.begin(true)) Serial.println("FFat Mount Failed");
//if (!LittleFS.begin(true)) Serial.println("LittleFS Mount Failed");
//if (!SD.begin(SS, SPI)) Serial.println("SD Mount Failed"); // replace SS and SPI to appropriate PINs with your board

/* second, begin TinyKeyValueStore after beginning FS class */
store.begin(STORE_FILE_NAME);

/* reading char variables from store */
store.getCharArray(KEY_WIFI_SSID, ssid);
store.getCharArray(KEY_WIFI_PSWD, pswd);
store.getCharArray(KEY_NTPD_HOST, host);

/* Check pressing BtnA or not when M5 just booting up */
M5.Display.printf("To configure WiFi,\nPlease press any button or touch display ...");
for (int i=0; i<500; i++) {
delay(10);
M5.update();
if (M5.BtnA.isPressed() || M5.BtnB.isPressed() || M5.BtnC.isPressed() || M5.Touch.getCount() > 0) {
config_mode = true;
break;
}
}
M5.Display.clear();
M5.Display.setCursor(0, 0);

if (config_mode) {
/* Pressed: WiFi config mode - Start WiFi AP and Web server */
WiFi.softAP(config_ssid);
WiFi.softAPConfig(dnsIP, dnsIP, IPAddress(255, 255, 255, 0));
dnsServer.start(DNS_PORT, "*", dnsIP);
/* Serve as CaptivePortal */
configServer.onNotFound(configWeb);
configServer.begin();
/**
* show ZXing's style WiFi connection QR
* see: https://zxing.appspot.com/generator
*/
String qrStr = "WIFI:S:" + String(config_ssid) + ";;";
M5.Display.qrcode(qrStr);
} else {
/* Not: Normal mode - NTP Client */
WiFi.mode(WIFI_STA); WiFi.disconnect();
M5.Display.printf("WiFi SSID: %s\n", ssid);
WiFi.begin(ssid, pswd);
while (WiFi.status() != WL_CONNECTED) {
if (millis() >= 60000UL) ESP.restart(); // reboot when couldnt connect within 1 min
M5.Display.print("."); delay(1000);
}
M5.Display.printf("\nConnected\nIP: %s\n", WiFi.localIP().toString().c_str());
/* Get time from NTP */
M5.Display.printf("\nNTP Host: %s\n", host);
configTime(0, 0, host);
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
M5.Display.printf("Time: failed to get\n");
} else {
M5.Display.printf("%04d-%02d-%02d %02d:%02d:%02d"
,timeinfo.tm_year + 1900
,timeinfo.tm_mon + 1
,timeinfo.tm_mday
,timeinfo.tm_hour
,timeinfo.tm_min
,timeinfo.tm_sec
);
}
}
}


void loop() {
/* Keep handling CaptivePortal when config mode */
if (config_mode) {
dnsServer.processNextRequest();
configServer.handleClient();
}
delay(1);
}
Loading

0 comments on commit f15443a

Please sign in to comment.