New setup so fresh reupload

This commit is contained in:
M-Factory
2025-07-14 23:37:38 +09:00
parent c46c24c17b
commit b1e2e4ad50
7 changed files with 3580 additions and 3580 deletions

File diff suppressed because it is too large Load Diff

1348
LICENSE

File diff suppressed because it is too large Load Diff

404
README.md
View File

@@ -1,202 +1,202 @@
![ESPTimeCast](assets/logo.svg)
**ESPTimeCast** is a WiFi-connected LED matrix clock and weather station based on ESP8266 and MAX7219.
It displays the current time, day of the week, and local weather (temp/humidity/weather description) fetched from OpenWeatherMap.
Setup and configuration are fully managed via a built-in web interface.
![clock - weather](assets/demo.gif)
<img src="assets/image01.png" alt="3D Printable Case" width="320" max-width="320" />
Get the 3D printable case!
[![Download on Printables](https://img.shields.io/badge/Printables-Download-orange?logo=prusa)](https://www.printables.com/model/1344276-esptimecast-wi-fi-clock-weather-display)
[![Available on Cults3D](https://img.shields.io/badge/Cults3D-Download-blue?logo=cults3d)](https://cults3d.com/en/3d-model/gadget/wifi-connected-led-matrix-clock-and-weather-station-esp8266-and-max7219)
---
## ✨ Features
- **LED Matrix Display (8x32)** powered by MAX7219, with custom font support
- **Simple Web Interface** for all configuration (WiFi, weather, time zone, display durations, and more)
- **Automatic NTP Sync** with robust status feedback and retries
- **Day of Week Display** with custom font
- **Weather Fetching** from OpenWeatherMap (every 5 minutes, temp/humidity/description)
- **Fallback AP Mode** for easy first-time setup or configuration
- **Timezone Selection** from IANA names (DST integrated on backend)
- **Day of the week display** in multiple languages
- **Persistent Config** stored in LittleFS, with backup/restore system
- **Status Animations** for WiFi conection, AP mode, time syncing.
- **Advanced Settings** panel with:
- Custom **Primary/Secondary NTP server** input
- Display **Day of the Week** toggle (defualt in on)
- **24/12h clock mode** toggle (24-hour default)
- **Imperial Units (°F)** toggle (metric °C defaults)
- Show **Humidity** toggle (display Humidity besides Temperature)
- **Weather description** toggle (displays: heavy rain, scattered clouds, thunderstorm etc.)
- **Flip display** (180 degrees)
- Adjustable display **brightness**
- Dimming Hours **Scheduling**
---
## 🪛 Wiring
Note: although the pins are labeled differently in the V4, the positions are the same as the V3.x
**Wemos D1 Mini (ESP8266) → MAX7219**
| Wemos D1 Mini (v3.x) | Wemos D1 Mini (v4.0) | MAX7219 |
|:-------------:|:-------:|:-------:|
| GND | GND | GND |
| D6 | 12 | CLK |
| D7 | 13 | CS |
| D8 | 15 | DIN |
| 3V3 | 3V3 | VCC |
<img src="assets/wiring.png" alt="Wiring" width="800" />
Note: Thanks to @Wood578Guy for the Wiring diagram and the info on V4
---
## 🌐 Web UI & Configuration
The built-in web interface provides full configuration for:
- **WiFi settings** (SSID & Password)
- **Weather settings** (OpenWeatherMap API key, City, Country, Coordinates)
- **Time zone** (will auto-populate if TZ is found)
- **Day of the week** languages
- **Display durations** for clock and weather (milliseconds)
- **Advanced Settings** (see below)
### First-time Setup / AP Mode
1. Power on the device. If WiFi fails, it auto-starts in AP mode:
- **SSID:** `ESPTimeCast`
- **Password:** `12345678`
- Open `http://192.168.4.1` or `http://setup.esp` in your browser.
2. Set your WiFi and all other options.
3. Click **Save Setting** the device saves config, reboots, and connects.
4. The device shows its local IP adress after boot so you can login again for setting changes
### UI Example:
<img src="assets/webui5.png" alt="Web Interface" width="320">
---
## ⚙️ Advanced Settings
Click the **cog icon** next to “Advanced Settings” in the web UI to reveal extra configuration options.
**Available advanced settings:**
- **Primary NTP Server**: Override the default NTP server (e.g. `pool.ntp.org`)
- **Secondary NTP Server**: Fallback NTP server (e.g. `time.nist.gov`)
- **Day of the Week**: Display Day of the Week in the disered language
- **24/12h Clock**: Switch between 24-hour and 12-hour time formats (24-hour default)
- **Imperial Units (°F)** toggle (metric °C defaults)
- **Humidity**: Display Humidity besides Temperature
- **Weather description** toggle (display weather description in the selected language* for 3 seconds or scrolls once if description is too long)
- **Flip Display**: Invert the display vertically/horizontally
- **Brightness**: 0 (dim) to 15 (bright)
- **Dimming Feature**: Start time, end time and desired brightness selection
*Non-English characters converted to their closest English alphabet.
Tip: Dont't forget to press the save button to keep your settings
---
## 📝 Configuration Notes
- **OpenWeatherMap API Key:** [Get yours here]([https://home.openweathermap.org/users/sign_up])
- **City Name:** e.g. `Tokyo`, `London`, etc.
- **Country Code:** 2-letter code (e.g., `JP`, `GB`)
- **ZIP Code:** Enter your ZIP code in the city field and US in the country field (US only)
- **Latitude and Longitude** You can enter coordinates in the city field (lat.) and country field (long.)
- **Time Zone:** Select from IANA zones (e.g., `America/New_York`, handles DST automatically)
---
## 🔧 Installation
1. **Clone this repo**
2. **Flash the ESP8266** using Arduino IDE or PlatformIO (Flash size "4MB FS:2MB OTA:~1019KB")
4. **Upload `/data` folder** with LittleFS uploader (see below)
### Board Setup
- Install ESP8266 board package:
`http://arduino.esp8266.com/stable/package_esp8266com_index.json`
- Select **Wemos D1 Mini** (or your ESP8266 variant) in Tools → Board
- Select Flash Size "4MB FS:2MB OTA:~1019KB" under Tools
### Dependencies
Install these libraries (Library Manager / PlatformIO):
- `ArduinoJson` by Benoit Blanchon
- `MD_Parola / MD_MAX72xx` all dependencies by majicDesigns
- `ESPAsyncTCP` by ESP32Async
- `ESPAsyncWebServer` by ESP32Async
### LittleFS Upload
Install the [LittleFS Uploader](https://randomnerdtutorials.com/arduino-ide-2-install-esp8266-littlefs/).
**To upload `/data`:**
1. Open Command Palette:
- Windows: `Ctrl+Shift+P`
- macOS: `Cmd+Shift+P`
2. Run: `Upload LittleFS to ESP8266`
**Important:** Serial Monitor **must be closed** before uploading!
---
## 📺 Display Behavior
**ESPTimeCast** automatically switches between two display modes: Clock and Weather.
If "Show Weather Description" is eneabled a third mode (Description) will display with a duration of 3 seconds, if the description is too long to fit on the display the description will scroll from right to left once.
What you see on the LED matrix depends on whether the device has successfully fetched the current time (via NTP) and weather (via OpenWeatherMap).
The following table summarizes what will appear on the display in each scenario:
| Display Mode | 🕒 NTP Time | 🌦️ Weather Data | 📺 Display Output |
|:------------:|:----------:|:--------------:|:--------------------------------------------|
| **Clock** | ✅ Yes | — | 🗓️ Day Icon + ⏰ Time (e.g. `@ 14:53`) |
| **Clock** | ❌ No | — | `! NTP` (NTP sync failed) |
| **Weather** | — | ✅ Yes | 🌡️ Temperature (e.g. `23ºC`) |
| **Weather** | ✅ Yes | ❌ No | 🗓️ Day Icon + ⏰ Time (e.g. `@ 14:53`) |
| **Weather** | ❌ No | ❌ No | `! TEMP` (no weather or time data) |
### **How it works:**
- The display automatically alternates between **Clock** and **Weather** modes (the duration for each is configurable).
- If "Show Weather Description" is eneabled a third mode **Description** will display after the **Weather** display with a duration of 3 seconds.
- In **Clock** mode, if NTP time is available, youll see the current time plus a unique day-of-week icon. If NTP is not available, you'll see `! NTP`.
- In **Weather** mode, if weather is available, youll see the temperature (like `23ºC`). If weather is not available but time is, it falls back to showing the clock. If neither is available, youll see `! TEMP`.
- All status/error messages (`! NTP`, `! TEMP`) are big icons shown on the dsiplay.
**Legend:**
- 🗓️ **Day Icon**: Custom symbol for day of week (`@`, `=`, etc.)
-**Time**: Current time (HH:MM)
- 🌡️ **Temperature**: Weather from OpenWeatherMap
-**Yes**: Data available
-**No**: Data not available
- — : Value does not affect this mode
---
## ☕ Support this project
If you like this project, you can [buy me a coffee](https://paypal.me/officialuphoto)!
![ESPTimeCast](assets/logo.svg)
**ESPTimeCast** is a WiFi-connected LED matrix clock and weather station based on ESP8266 and MAX7219.
It displays the current time, day of the week, and local weather (temp/humidity/weather description) fetched from OpenWeatherMap.
Setup and configuration are fully managed via a built-in web interface.
![clock - weather](assets/demo.gif)
<img src="assets/image01.png" alt="3D Printable Case" width="320" max-width="320" />
Get the 3D printable case!
[![Download on Printables](https://img.shields.io/badge/Printables-Download-orange?logo=prusa)](https://www.printables.com/model/1344276-esptimecast-wi-fi-clock-weather-display)
[![Available on Cults3D](https://img.shields.io/badge/Cults3D-Download-blue?logo=cults3d)](https://cults3d.com/en/3d-model/gadget/wifi-connected-led-matrix-clock-and-weather-station-esp8266-and-max7219)
---
## ✨ Features
- **LED Matrix Display (8x32)** powered by MAX7219, with custom font support
- **Simple Web Interface** for all configuration (WiFi, weather, time zone, display durations, and more)
- **Automatic NTP Sync** with robust status feedback and retries
- **Day of Week Display** with custom font
- **Weather Fetching** from OpenWeatherMap (every 5 minutes, temp/humidity/description)
- **Fallback AP Mode** for easy first-time setup or configuration
- **Timezone Selection** from IANA names (DST integrated on backend)
- **Day of the week display** in multiple languages
- **Persistent Config** stored in LittleFS, with backup/restore system
- **Status Animations** for WiFi conection, AP mode, time syncing.
- **Advanced Settings** panel with:
- Custom **Primary/Secondary NTP server** input
- Display **Day of the Week** toggle (defualt in on)
- **24/12h clock mode** toggle (24-hour default)
- **Imperial Units (°F)** toggle (metric °C defaults)
- Show **Humidity** toggle (display Humidity besides Temperature)
- **Weather description** toggle (displays: heavy rain, scattered clouds, thunderstorm etc.)
- **Flip display** (180 degrees)
- Adjustable display **brightness**
- Dimming Hours **Scheduling**
---
## 🪛 Wiring
Note: although the pins are labeled differently in the V4, the positions are the same as the V3.x
**Wemos D1 Mini (ESP8266) → MAX7219**
| Wemos D1 Mini (v3.x) | Wemos D1 Mini (v4.0) | MAX7219 |
|:-------------:|:-------:|:-------:|
| GND | GND | GND |
| D6 | 12 | CLK |
| D7 | 13 | CS |
| D8 | 15 | DIN |
| 3V3 | 3V3 | VCC |
<img src="assets/wiring.png" alt="Wiring" width="800" />
Note: Thanks to @Wood578Guy for the Wiring diagram and the info on V4
---
## 🌐 Web UI & Configuration
The built-in web interface provides full configuration for:
- **WiFi settings** (SSID & Password)
- **Weather settings** (OpenWeatherMap API key, City, Country, Coordinates)
- **Time zone** (will auto-populate if TZ is found)
- **Day of the week** languages
- **Display durations** for clock and weather (milliseconds)
- **Advanced Settings** (see below)
### First-time Setup / AP Mode
1. Power on the device. If WiFi fails, it auto-starts in AP mode:
- **SSID:** `ESPTimeCast`
- **Password:** `12345678`
- Open `http://192.168.4.1` or `http://setup.esp` in your browser.
2. Set your WiFi and all other options.
3. Click **Save Setting** the device saves config, reboots, and connects.
4. The device shows its local IP adress after boot so you can login again for setting changes
### UI Example:
<img src="assets/webui5.png" alt="Web Interface" width="320">
---
## ⚙️ Advanced Settings
Click the **cog icon** next to “Advanced Settings” in the web UI to reveal extra configuration options.
**Available advanced settings:**
- **Primary NTP Server**: Override the default NTP server (e.g. `pool.ntp.org`)
- **Secondary NTP Server**: Fallback NTP server (e.g. `time.nist.gov`)
- **Day of the Week**: Display Day of the Week in the disered language
- **24/12h Clock**: Switch between 24-hour and 12-hour time formats (24-hour default)
- **Imperial Units (°F)** toggle (metric °C defaults)
- **Humidity**: Display Humidity besides Temperature
- **Weather description** toggle (display weather description in the selected language* for 3 seconds or scrolls once if description is too long)
- **Flip Display**: Invert the display vertically/horizontally
- **Brightness**: 0 (dim) to 15 (bright)
- **Dimming Feature**: Start time, end time and desired brightness selection
*Non-English characters converted to their closest English alphabet.
Tip: Dont't forget to press the save button to keep your settings
---
## 📝 Configuration Notes
- **OpenWeatherMap API Key:** [Get yours here]([https://home.openweathermap.org/users/sign_up])
- **City Name:** e.g. `Tokyo`, `London`, etc.
- **Country Code:** 2-letter code (e.g., `JP`, `GB`)
- **ZIP Code:** Enter your ZIP code in the city field and US in the country field (US only)
- **Latitude and Longitude** You can enter coordinates in the city field (lat.) and country field (long.)
- **Time Zone:** Select from IANA zones (e.g., `America/New_York`, handles DST automatically)
---
## 🔧 Installation
1. **Clone this repo**
2. **Flash the ESP8266** using Arduino IDE or PlatformIO (Flash size "4MB FS:2MB OTA:~1019KB")
4. **Upload `/data` folder** with LittleFS uploader (see below)
### Board Setup
- Install ESP8266 board package:
`http://arduino.esp8266.com/stable/package_esp8266com_index.json`
- Select **Wemos D1 Mini** (or your ESP8266 variant) in Tools → Board
- Select Flash Size "4MB FS:2MB OTA:~1019KB" under Tools
### Dependencies
Install these libraries (Library Manager / PlatformIO):
- `ArduinoJson` by Benoit Blanchon
- `MD_Parola / MD_MAX72xx` all dependencies by majicDesigns
- `ESPAsyncTCP` by ESP32Async
- `ESPAsyncWebServer` by ESP32Async
### LittleFS Upload
Install the [LittleFS Uploader](https://randomnerdtutorials.com/arduino-ide-2-install-esp8266-littlefs/).
**To upload `/data`:**
1. Open Command Palette:
- Windows: `Ctrl+Shift+P`
- macOS: `Cmd+Shift+P`
2. Run: `Upload LittleFS to ESP8266`
**Important:** Serial Monitor **must be closed** before uploading!
---
## 📺 Display Behavior
**ESPTimeCast** automatically switches between two display modes: Clock and Weather.
If "Show Weather Description" is eneabled a third mode (Description) will display with a duration of 3 seconds, if the description is too long to fit on the display the description will scroll from right to left once.
What you see on the LED matrix depends on whether the device has successfully fetched the current time (via NTP) and weather (via OpenWeatherMap).
The following table summarizes what will appear on the display in each scenario:
| Display Mode | 🕒 NTP Time | 🌦️ Weather Data | 📺 Display Output |
|:------------:|:----------:|:--------------:|:--------------------------------------------|
| **Clock** | ✅ Yes | — | 🗓️ Day Icon + ⏰ Time (e.g. `@ 14:53`) |
| **Clock** | ❌ No | — | `! NTP` (NTP sync failed) |
| **Weather** | — | ✅ Yes | 🌡️ Temperature (e.g. `23ºC`) |
| **Weather** | ✅ Yes | ❌ No | 🗓️ Day Icon + ⏰ Time (e.g. `@ 14:53`) |
| **Weather** | ❌ No | ❌ No | `! TEMP` (no weather or time data) |
### **How it works:**
- The display automatically alternates between **Clock** and **Weather** modes (the duration for each is configurable).
- If "Show Weather Description" is eneabled a third mode **Description** will display after the **Weather** display with a duration of 3 seconds.
- In **Clock** mode, if NTP time is available, youll see the current time plus a unique day-of-week icon. If NTP is not available, you'll see `! NTP`.
- In **Weather** mode, if weather is available, youll see the temperature (like `23ºC`). If weather is not available but time is, it falls back to showing the clock. If neither is available, youll see `! TEMP`.
- All status/error messages (`! NTP`, `! TEMP`) are big icons shown on the dsiplay.
**Legend:**
- 🗓️ **Day Icon**: Custom symbol for day of week (`@`, `=`, etc.)
-**Time**: Current time (HH:MM)
- 🌡️ **Temperature**: Weather from OpenWeatherMap
-**Yes**: Data available
-**No**: Data not available
- — : Value does not affect this mode
---
## ☕ Support this project
If you like this project, you can [buy me a coffee](https://paypal.me/officialuphoto)!

View File

@@ -1,19 +1,19 @@
{
"ssid": "",
"password": "",
"openWeatherApiKey": "",
"openWeatherCity": "",
"openWeatherCountry": "",
"clockDuration": 10000,
"weatherDuration": 5000,
"timeZone": "",
"weatherUnits": "metric",
"brightness": 10,
"flipDisplay": false,
"ntpServer1": "pool.ntp.org",
"ntpServer2": "time.nist.gov",
"twelveHourToggle": false,
"showDayOfWeek": true,
"showHumidity": false,
"language": "en"
{
"ssid": "",
"password": "",
"openWeatherApiKey": "",
"openWeatherCity": "",
"openWeatherCountry": "",
"clockDuration": 10000,
"weatherDuration": 5000,
"timeZone": "",
"weatherUnits": "metric",
"brightness": 10,
"flipDisplay": false,
"ntpServer1": "pool.ntp.org",
"ntpServer2": "time.nist.gov",
"twelveHourToggle": false,
"showDayOfWeek": true,
"showHumidity": false,
"language": "en"
}

File diff suppressed because one or more lines are too long

View File

@@ -1,49 +1,49 @@
#ifndef DAYS_LOOKUP_H
#define DAYS_LOOKUP_H
typedef struct {
const char* lang;
const char* days[7]; // Sunday to Saturday (tm_wday order)
} DaysOfWeekMapping;
const DaysOfWeekMapping days_mappings[] = {
{ "af", { "s&u&n", "m&a&a", "d&i&n", "w&o&e", "d&o&n", "v&r&y", "s&o&n" } },
{ "cs", { "n&e&d", "p&o&n", "u&t&e", "s&t&r", "c&t&v", "p&a&t", "s&o&b" } },
{ "da", { "s&o&n", "m&a&n", "t&i&r", "o&n&s", "t&o&r", "f&r&e", "l&o&r" } },
{ "de", { "s&o&n", "m&o&n", "d&i&e", "m&i&t", "d&o&n", "f&r&e", "s&a&m" } },
{ "en", { "s&u&n", "m&o&n", "t&u&e", "w&e&d", "t&h&u", "f&r&i", "s&a&t" } },
{ "eo", { "d&i&m", "l&u&n", "m&a&r", "m&e&r", "j&a&u", "v&e&n", "s&a&b" } },
{ "es", { "d&o&m", "l&u&n", "m&a&r", "m&i&e", "j&u&e", "v&i&e", "s&a&b" } },
{ "et", { "p&a", "e&s", "t&e", "k&o", "n&e", "r&e", "l&a" } },
{ "fi", { "s&u&n", "m&a&a", "t&i&s", "k&e&s", "t&o&r", "p&e&r", "l&a&u" } },
{ "fr", { "d&i&m", "l&u&n", "m&a&r", "m&e&r", "j&e&u", "v&e&n", "s&a&m" } },
{ "hr", { "n&e&d", "p&o&n", "u&t&o", "s&r&i", "c&e&t", "p&e&t", "s&u&b" } },
{ "hu", { "v&a&s", "h&e&t", "k&e&d", "s&z&e", "c&s&u", "p&e&t", "s&z&o" } },
{ "it", { "d&o&m", "l&u&n", "m&a&r", "m&e&r", "g&i&o", "v&e&n", "s&a&b" } },
{ "ja", { "±", "²", "³", "´", "µ", "", "·" } },
{ "lt", { "s&e&k", "p&i&r", "a&n&t", "t&r&e", "k&e&t", "p&e&n", "s&e&s" } },
{ "lv", { "s&v&e", "p&i&r", "o&t&r", "t&r&e", "c&e&t", "p&i&e", "s&e&s" } },
{ "nl", { "z&o&n", "m&a&a", "d&i&n", "w&o&e", "d&o&n", "v&r&i", "z&a&t" } },
{ "no", { "s&o&n", "m&a&n", "t&i&r", "o&n&s", "t&o&r", "f&r&e", "l&o&r" } },
{ "pl", { "n&i&e", "p&o&n", "w&t&o", "s&r&o", "c&z&w", "p&i&a", "s&o&b" } },
{ "pt", { "d&o&m", "s&e&g", "t&e&r", "q&u&a", "q&u&i", "s&e&x", "s&a&b" } },
{ "ro", { "d&u&m", "l&u&n", "m&a&r", "m&i&e", "j&o&i", "v&i&n", "s&a&m" } },
{ "sk", { "n&e&d", "p&o&n", "u&t&o", "s&t&r", "s&t&v", "p&i&a", "s&o&b" } },
{ "sl", { "n&e&d", "p&o&n", "t&o&r", "s&r&e", "c&e&t", "p&e&t", "s&o&b" } },
{ "sv", { "s&o&n", "m&a&n", "t&i&s", "o&n&s", "t&o&r", "f&r&e", "l&o&r" } },
{ "sw", { "j&p&l", "j&u&m", "j&t&t", "j&t&n", "a&l&k", "i&j&m", "j&m&s" } },
{ "tr", { "p&a&z", "p&a&z", "s&a&l", "c&a&r", "p&e&r", "c&u&m", "c&u&m" } }
};
#define DAYS_MAPPINGS_COUNT (sizeof(days_mappings)/sizeof(days_mappings[0]))
inline const char* const* getDaysOfWeek(const char* lang) {
for (size_t i = 0; i < DAYS_MAPPINGS_COUNT; i++) {
if (strcmp(lang, days_mappings[i].lang) == 0)
return days_mappings[i].days;
}
// fallback to English if not found
return days_mappings[4].days; // "en" is index 4
}
#ifndef DAYS_LOOKUP_H
#define DAYS_LOOKUP_H
typedef struct {
const char* lang;
const char* days[7]; // Sunday to Saturday (tm_wday order)
} DaysOfWeekMapping;
const DaysOfWeekMapping days_mappings[] = {
{ "af", { "s&u&n", "m&a&a", "d&i&n", "w&o&e", "d&o&n", "v&r&y", "s&o&n" } },
{ "cs", { "n&e&d", "p&o&n", "u&t&e", "s&t&r", "c&t&v", "p&a&t", "s&o&b" } },
{ "da", { "s&o&n", "m&a&n", "t&i&r", "o&n&s", "t&o&r", "f&r&e", "l&o&r" } },
{ "de", { "s&o&n", "m&o&n", "d&i&e", "m&i&t", "d&o&n", "f&r&e", "s&a&m" } },
{ "en", { "s&u&n", "m&o&n", "t&u&e", "w&e&d", "t&h&u", "f&r&i", "s&a&t" } },
{ "eo", { "d&i&m", "l&u&n", "m&a&r", "m&e&r", "j&a&u", "v&e&n", "s&a&b" } },
{ "es", { "d&o&m", "l&u&n", "m&a&r", "m&i&e", "j&u&e", "v&i&e", "s&a&b" } },
{ "et", { "p&a", "e&s", "t&e", "k&o", "n&e", "r&e", "l&a" } },
{ "fi", { "s&u&n", "m&a&a", "t&i&s", "k&e&s", "t&o&r", "p&e&r", "l&a&u" } },
{ "fr", { "d&i&m", "l&u&n", "m&a&r", "m&e&r", "j&e&u", "v&e&n", "s&a&m" } },
{ "hr", { "n&e&d", "p&o&n", "u&t&o", "s&r&i", "c&e&t", "p&e&t", "s&u&b" } },
{ "hu", { "v&a&s", "h&e&t", "k&e&d", "s&z&e", "c&s&u", "p&e&t", "s&z&o" } },
{ "it", { "d&o&m", "l&u&n", "m&a&r", "m&e&r", "g&i&o", "v&e&n", "s&a&b" } },
{ "ja", { "±", "²", "³", "´", "µ", "", "·" } },
{ "lt", { "s&e&k", "p&i&r", "a&n&t", "t&r&e", "k&e&t", "p&e&n", "s&e&s" } },
{ "lv", { "s&v&e", "p&i&r", "o&t&r", "t&r&e", "c&e&t", "p&i&e", "s&e&s" } },
{ "nl", { "z&o&n", "m&a&a", "d&i&n", "w&o&e", "d&o&n", "v&r&i", "z&a&t" } },
{ "no", { "s&o&n", "m&a&n", "t&i&r", "o&n&s", "t&o&r", "f&r&e", "l&o&r" } },
{ "pl", { "n&i&e", "p&o&n", "w&t&o", "s&r&o", "c&z&w", "p&i&a", "s&o&b" } },
{ "pt", { "d&o&m", "s&e&g", "t&e&r", "q&u&a", "q&u&i", "s&e&x", "s&a&b" } },
{ "ro", { "d&u&m", "l&u&n", "m&a&r", "m&i&e", "j&o&i", "v&i&n", "s&a&m" } },
{ "sk", { "n&e&d", "p&o&n", "u&t&o", "s&t&r", "s&t&v", "p&i&a", "s&o&b" } },
{ "sl", { "n&e&d", "p&o&n", "t&o&r", "s&r&e", "c&e&t", "p&e&t", "s&o&b" } },
{ "sv", { "s&o&n", "m&a&n", "t&i&s", "o&n&s", "t&o&r", "f&r&e", "l&o&r" } },
{ "sw", { "j&p&l", "j&u&m", "j&t&t", "j&t&n", "a&l&k", "i&j&m", "j&m&s" } },
{ "tr", { "p&a&z", "p&a&z", "s&a&l", "c&a&r", "p&e&r", "c&u&m", "c&u&m" } }
};
#define DAYS_MAPPINGS_COUNT (sizeof(days_mappings)/sizeof(days_mappings[0]))
inline const char* const* getDaysOfWeek(const char* lang) {
for (size_t i = 0; i < DAYS_MAPPINGS_COUNT; i++) {
if (strcmp(lang, days_mappings[i].lang) == 0)
return days_mappings[i].days;
}
// fallback to English if not found
return days_mappings[4].days; // "en" is index 4
}
#endif // DAYS_LOOKUP_H

View File

@@ -1,262 +1,262 @@
// Data file for user example user defined fonts
#pragma once
MD_MAX72XX::fontType_t mFactory[] PROGMEM =
{
1, 0, // 0 - 'Empty Cell'
1, 0, // 1 - 'Sad Smiley'
1, 0, // 2 - 'Happy Smiley'
1, 0, // 3 - 'Heart'
1, 0, // 4 - 'Diamond'
1, 0, // 5 - 'Clubs'
1, 0, // 6 - 'Spades'
1, 0, // 7 - 'Bullet Point'
1, 0, // 8 - 'Rev Bullet Point'
1, 0, // 9 - 'Hollow Bullet Point'
1, 0, // 10 - 'Rev Hollow BP'
1, 0, // 11 - 'Male'
1, 0, // 12 - 'Female'
1, 0, // 13 - 'Music Note 1'
1, 0, // 14 - 'Music Note 2'
1, 0, // 15 - 'Snowflake'
1, 0, // 16 - 'Right Pointer'
1, 0, // 17 - 'Left Pointer'
1, 0, // 18 - 'UpDown Arrows'
1, 0, // 19 - 'Full Block'
1, 0, // 20 - 'Half Block Bottom'
1, 0, // 21 - 'Half Block LHS'
1, 0, // 22 - 'Half Block RHS'
1, 0, // 23 - 'Half Block Top'
1, 0, // 24 - 'Up Arrow'
1, 0, // 25 - 'Down Arrow'
1, 0, // 26 - 'Right Arrow'
1, 0, // 27 - 'Left Arrow'
1, 0, // 28 - '30% shading'
1, 0, // 29 - '50% shading'
1, 0, // 30 - 'Up Pointer'
1, 0, // 31 - 'Down Pointer'
1, 0, // 32 - 'Space'
1, 0, // 33 - '!'
1, 0, // 34 - '""'
13, 63, 192, 127, 192, 63, 0, 250, 0, 255, 9, 1, 0, 250, // 35 - '#'
16, 72, 84, 36, 0, 12, 112, 12, 0, 124, 4, 120, 0, 56, 68, 68, 0, // 36 - '$'
6, 66, 37, 18, 72, 164, 66, // 37 - '%'
1, 1, // 38 - '&'
1, 0, // 39 - ''
1, 0, // 40 - '('
1, 0, // 41 - ')'
20, 250, 130, 250, 254, 130, 170, 186, 254, 130, 250, 226, 250, 134, 254, 130, 234, 234, 246, 254, 124, // 42 - '*'
1, 0, // 43 - '+'
3, 64, 0, 0, // 44 - ','
2, 8, 8, // 45 - '-'
1, 128, // 46 - '.'
15, 130, 246, 238, 130, 254, 250, 130, 250, 254, 130, 234, 234, 246, 254, 124, // 47 - '/'
3, 126, 129, 126, // 48 - '0'
2, 2, 255, // 49 - '1'
3, 194, 177, 142, // 50 - '2'
3, 66, 137, 118, // 51 - '3'
3, 15, 8, 255, // 52 - '4'
3, 79, 137, 113, // 53 - '5'
3, 126, 137, 114, // 54 - '6'
3, 1, 249, 7, // 55 - '7'
3, 118, 137, 118, // 56 - '8'
3, 78, 145, 126, // 57 - '9'
1, 36, // 58 - ':'
1, 0, // 59 - ';'
1, 0, // 60 - '<'
9, 254, 17, 17, 254, 0, 255, 17, 17, 14, // 61 - '='
1, 0, // 62 - '>'
7, 124, 254, 254, 162, 254, 254, 254, // 63 - '?'
1, 250, // 64 - '@'
3, 124, 10, 124, // 65 - 'A'
3, 126, 74, 52, // 66 - 'B'
3, 60, 66, 36, // 67 - 'C'
3, 126, 66, 60, // 68 - 'D'
3, 126, 74, 66, // 69 - 'E'
3, 126, 10, 2, // 70 - 'F'
3, 60, 82, 116, // 71 - 'G'
3, 126, 8, 126, // 72 - 'H'
1, 126, // 73 - 'I'
3, 32, 64, 62, // 74 - 'J'
3, 126, 8, 118, // 75 - 'K'
3, 126, 64, 64, // 76 - 'L'
3, 126, 4, 126, // 77 - 'M'
3, 126, 2, 124, // 78 - 'N'
3, 60, 66, 60, // 79 - 'O'
3, 126, 18, 12, // 80 - 'P'
3, 60, 66, 124, // 81 - 'Q'
3, 126, 18, 108, // 82 - 'R'
3, 68, 74, 50, // 83 - 'S'
3, 2, 126, 2, // 84 - 'T'
3, 62, 64, 62, // 85 - 'U'
3, 30, 96, 30, // 86 - 'V'
3, 126, 32, 126, // 87 - 'W'
3, 118, 8, 118, // 88 - 'X'
3, 6, 120, 6, // 89 - 'Y'
3, 98, 90, 70, // 90 - 'Z'
4, 126, 129, 129, 66, // 91 - '['
3, 6, 28, 48, // 92 - '\'
4, 255, 9, 9, 1, // 93 - ']'
3, 8, 4, 8, // 94 - '^'
3, 32, 32, 32, // 95 - '_'
4, 255, 8, 20, 227, // 96 - '`'
3, 249, 21, 249, // 97 - 'a'
3, 253, 149, 105, // 98 - 'b'
3, 121, 133, 73, // 99 - 'c'
3, 253, 133, 121, // 100 - 'd'
3, 253, 149, 133, // 101 - 'e'
3, 253, 21, 5, // 102 - 'f'
3, 121, 165, 233, // 103 - 'g'
3, 253, 17, 253, // 104 - 'h'
3, 1, 253, 1, // 105 - 'i'
3, 65, 129, 125, // 106 - 'j'
3, 253, 17, 237, // 107 - 'k'
3, 253, 129, 129, // 108 - 'l'
3, 253, 9, 253, // 109 - 'm'
3, 253, 5, 249, // 110 - 'n'
3, 121, 133, 121, // 111 - 'o'
3, 253, 37, 25, // 112 - 'p'
3, 121, 133, 249, // 113 - 'q'
3, 253, 37, 217, // 114 - 'r'
3, 137, 149, 101, // 115 - 's'
3, 5, 253, 5, // 116 - 't'
3, 125, 129, 125, // 117 - 'u'
3, 61, 193, 61, // 118 - 'v'
3, 253, 65, 253, // 119 - 'w'
3, 237, 17, 237, // 120 - 'x'
3, 13, 241, 13, // 121 - 'y'
3, 197, 181, 141, // 122 - 'z'
1, 0, // 123 - '{'
1, 0, // 124 - '|'
1, 0, // 125 - '}'
0, // 126 - '~'
0, // 127 - ''
0, // 128 - '€'
0, // 129 - ''
0, // 130 - ''
0, // 131 - 'ƒ'
0, // 132 - '„'
0, // 133 - '…'
0, // 134 - '†'
0, // 135 - '‡'
0, // 136 - 'ˆ'
0, // 137 - '‰'
0, // 138 - 'Š'
0, // 139 - ''
0, // 140 - 'Œ'
0, // 141 - ''
0, // 142 - 'Ž'
0, // 143 - ''
0, // 144 - ''
0, // 145 - ''
0, // 146 - ''
0, // 147 - '“'
0, // 148 - '”'
1, 0, // 149 - '•'
1, 0, // 150 - ''
1, 0, // 151 - '—'
0, // 152 - '˜'
0, // 153 - '™'
0, // 154 - 'š'
0, // 155 - ''
0, // 156 - 'œ'
0, // 157 - ''
0, // 158 - 'ž'
0, // 159 - 'Ÿ'
0, // 160 - ''
0, // 161 - '¡'
0, // 162 - '¢'
0, // 163 - '£'
0, // 164 - '¤'
0, // 165 - '¥'
0, // 166 - '¦'
0, // 167 - '§'
0, // 168 - '¨'
8, 224, 224, 0, 0, 0, 0, 0, 0, // 169 - '©'
8, 224, 224, 0, 252, 252, 0, 0, 0, // 170 - 'ª'
8, 224, 224, 0, 252, 252, 0, 255, 255, // 171 - '«'
0, // 172 - '¬'
0, // 173 - '­'
5, 64, 0, 0, 0, 0, // 174 - '®'
5, 64, 0, 64, 0, 0, // 175 - '¯'
5, 64, 0, 64, 0, 64, // 176 - '°'
6, 254, 146, 146, 146, 254, 0, // 177 - '±'
7, 128, 126, 42, 42, 170, 254, 0, // 178 - '²'
8, 128, 152, 64, 62, 80, 136, 128, 0, // 179 - '³'
8, 72, 40, 152, 254, 16, 40, 68, 0, // 180 - '´'
8, 68, 36, 20, 254, 20, 36, 68, 0, // 181 - 'µ'
8, 168, 232, 172, 250, 172, 232, 168, 0, // 182 - '¶'
8, 128, 136, 136, 254, 136, 136, 128, 0, // 183 - '·'
0, // 184 - '¸'
0, // 185 - '¹'
3, 4, 10, 4, // 186 - 'º'
0, // 187 - '»'
0, // 188 - '¼'
0, // 189 - '½'
0, // 190 - '¾'
0, // 191 - '¿'
0, // 192 - 'À'
0, // 193 - 'Á'
0, // 194 - 'Â'
0, // 195 - 'Ã'
0, // 196 - 'Ä'
0, // 197 - 'Å'
0, // 198 - 'Æ'
0, // 199 - 'Ç'
0, // 200 - 'È'
0, // 201 - 'É'
0, // 202 - 'Ê'
0, // 203 - 'Ë'
0, // 204 - 'Ì'
0, // 205 - 'Í'
0, // 206 - 'Î'
0, // 207 - 'Ï'
0, // 208 - 'Ð'
0, // 209 - 'Ñ'
0, // 210 - 'Ò'
0, // 211 - 'Ó'
0, // 212 - 'Ô'
0, // 213 - 'Õ'
0, // 214 - 'Ö'
0, // 215 - '×'
0, // 216 - 'Ø'
0, // 217 - 'Ù'
0, // 218 - 'Ú'
0, // 219 - 'Û'
0, // 220 - 'Ü'
0, // 221 - 'Ý'
0, // 222 - 'Þ'
0, // 223 - 'ß'
0, // 224 - 'à'
0, // 225 - 'á'
0, // 226 - 'â'
0, // 227 - 'ã'
0, // 228 - 'ä'
0, // 229 - 'å'
0, // 230 - 'æ'
0, // 231 - 'ç'
0, // 232 - 'è'
0, // 233 - 'é'
0, // 234 - 'ê'
0, // 235 - 'ë'
0, // 236 - 'ì'
0, // 237 - 'í'
0, // 238 - 'î'
0, // 239 - 'ï'
0, // 240 - 'ð'
0, // 241 - 'ñ'
0, // 242 - 'ò'
0, // 243 - 'ó'
0, // 244 - 'ô'
0, // 245 - 'õ'
0, // 246 - 'ö'
0, // 247 - '÷'
0, // 248 - 'ø'
0, // 249 - 'ù'
0, // 250 - 'ú'
0, // 251 - 'û'
0, // 252 - 'ü'
0, // 253 - 'ý'
0, // 254 - 'þ'
0, // 255 - 'ÿ'
};
// Data file for user example user defined fonts
#pragma once
MD_MAX72XX::fontType_t mFactory[] PROGMEM =
{
1, 0, // 0 - 'Empty Cell'
1, 0, // 1 - 'Sad Smiley'
1, 0, // 2 - 'Happy Smiley'
1, 0, // 3 - 'Heart'
1, 0, // 4 - 'Diamond'
1, 0, // 5 - 'Clubs'
1, 0, // 6 - 'Spades'
1, 0, // 7 - 'Bullet Point'
1, 0, // 8 - 'Rev Bullet Point'
1, 0, // 9 - 'Hollow Bullet Point'
1, 0, // 10 - 'Rev Hollow BP'
1, 0, // 11 - 'Male'
1, 0, // 12 - 'Female'
1, 0, // 13 - 'Music Note 1'
1, 0, // 14 - 'Music Note 2'
1, 0, // 15 - 'Snowflake'
1, 0, // 16 - 'Right Pointer'
1, 0, // 17 - 'Left Pointer'
1, 0, // 18 - 'UpDown Arrows'
1, 0, // 19 - 'Full Block'
1, 0, // 20 - 'Half Block Bottom'
1, 0, // 21 - 'Half Block LHS'
1, 0, // 22 - 'Half Block RHS'
1, 0, // 23 - 'Half Block Top'
1, 0, // 24 - 'Up Arrow'
1, 0, // 25 - 'Down Arrow'
1, 0, // 26 - 'Right Arrow'
1, 0, // 27 - 'Left Arrow'
1, 0, // 28 - '30% shading'
1, 0, // 29 - '50% shading'
1, 0, // 30 - 'Up Pointer'
1, 0, // 31 - 'Down Pointer'
1, 0, // 32 - 'Space'
1, 0, // 33 - '!'
1, 0, // 34 - '""'
13, 63, 192, 127, 192, 63, 0, 250, 0, 255, 9, 1, 0, 250, // 35 - '#'
16, 72, 84, 36, 0, 12, 112, 12, 0, 124, 4, 120, 0, 56, 68, 68, 0, // 36 - '$'
6, 66, 37, 18, 72, 164, 66, // 37 - '%'
1, 1, // 38 - '&'
1, 0, // 39 - ''
1, 0, // 40 - '('
1, 0, // 41 - ')'
20, 250, 130, 250, 254, 130, 170, 186, 254, 130, 250, 226, 250, 134, 254, 130, 234, 234, 246, 254, 124, // 42 - '*'
1, 0, // 43 - '+'
3, 64, 0, 0, // 44 - ','
2, 8, 8, // 45 - '-'
1, 128, // 46 - '.'
15, 130, 246, 238, 130, 254, 250, 130, 250, 254, 130, 234, 234, 246, 254, 124, // 47 - '/'
3, 126, 129, 126, // 48 - '0'
2, 2, 255, // 49 - '1'
3, 194, 177, 142, // 50 - '2'
3, 66, 137, 118, // 51 - '3'
3, 15, 8, 255, // 52 - '4'
3, 79, 137, 113, // 53 - '5'
3, 126, 137, 114, // 54 - '6'
3, 1, 249, 7, // 55 - '7'
3, 118, 137, 118, // 56 - '8'
3, 78, 145, 126, // 57 - '9'
1, 36, // 58 - ':'
1, 0, // 59 - ';'
1, 0, // 60 - '<'
9, 254, 17, 17, 254, 0, 255, 17, 17, 14, // 61 - '='
1, 0, // 62 - '>'
7, 124, 254, 254, 162, 254, 254, 254, // 63 - '?'
1, 250, // 64 - '@'
3, 124, 10, 124, // 65 - 'A'
3, 126, 74, 52, // 66 - 'B'
3, 60, 66, 36, // 67 - 'C'
3, 126, 66, 60, // 68 - 'D'
3, 126, 74, 66, // 69 - 'E'
3, 126, 10, 2, // 70 - 'F'
3, 60, 82, 116, // 71 - 'G'
3, 126, 8, 126, // 72 - 'H'
1, 126, // 73 - 'I'
3, 32, 64, 62, // 74 - 'J'
3, 126, 8, 118, // 75 - 'K'
3, 126, 64, 64, // 76 - 'L'
3, 126, 4, 126, // 77 - 'M'
3, 126, 2, 124, // 78 - 'N'
3, 60, 66, 60, // 79 - 'O'
3, 126, 18, 12, // 80 - 'P'
3, 60, 66, 124, // 81 - 'Q'
3, 126, 18, 108, // 82 - 'R'
3, 68, 74, 50, // 83 - 'S'
3, 2, 126, 2, // 84 - 'T'
3, 62, 64, 62, // 85 - 'U'
3, 30, 96, 30, // 86 - 'V'
3, 126, 32, 126, // 87 - 'W'
3, 118, 8, 118, // 88 - 'X'
3, 6, 120, 6, // 89 - 'Y'
3, 98, 90, 70, // 90 - 'Z'
4, 126, 129, 129, 66, // 91 - '['
3, 6, 28, 48, // 92 - '\'
4, 255, 9, 9, 1, // 93 - ']'
3, 8, 4, 8, // 94 - '^'
3, 32, 32, 32, // 95 - '_'
4, 255, 8, 20, 227, // 96 - '`'
3, 249, 21, 249, // 97 - 'a'
3, 253, 149, 105, // 98 - 'b'
3, 121, 133, 73, // 99 - 'c'
3, 253, 133, 121, // 100 - 'd'
3, 253, 149, 133, // 101 - 'e'
3, 253, 21, 5, // 102 - 'f'
3, 121, 165, 233, // 103 - 'g'
3, 253, 17, 253, // 104 - 'h'
3, 1, 253, 1, // 105 - 'i'
3, 65, 129, 125, // 106 - 'j'
3, 253, 17, 237, // 107 - 'k'
3, 253, 129, 129, // 108 - 'l'
3, 253, 9, 253, // 109 - 'm'
3, 253, 5, 249, // 110 - 'n'
3, 121, 133, 121, // 111 - 'o'
3, 253, 37, 25, // 112 - 'p'
3, 121, 133, 249, // 113 - 'q'
3, 253, 37, 217, // 114 - 'r'
3, 137, 149, 101, // 115 - 's'
3, 5, 253, 5, // 116 - 't'
3, 125, 129, 125, // 117 - 'u'
3, 61, 193, 61, // 118 - 'v'
3, 253, 65, 253, // 119 - 'w'
3, 237, 17, 237, // 120 - 'x'
3, 13, 241, 13, // 121 - 'y'
3, 197, 181, 141, // 122 - 'z'
1, 0, // 123 - '{'
1, 0, // 124 - '|'
1, 0, // 125 - '}'
0, // 126 - '~'
0, // 127 - ''
0, // 128 - '€'
0, // 129 - ''
0, // 130 - ''
0, // 131 - 'ƒ'
0, // 132 - '„'
0, // 133 - '…'
0, // 134 - '†'
0, // 135 - '‡'
0, // 136 - 'ˆ'
0, // 137 - '‰'
0, // 138 - 'Š'
0, // 139 - ''
0, // 140 - 'Œ'
0, // 141 - ''
0, // 142 - 'Ž'
0, // 143 - ''
0, // 144 - ''
0, // 145 - ''
0, // 146 - ''
0, // 147 - '“'
0, // 148 - '”'
1, 0, // 149 - '•'
1, 0, // 150 - ''
1, 0, // 151 - '—'
0, // 152 - '˜'
0, // 153 - '™'
0, // 154 - 'š'
0, // 155 - ''
0, // 156 - 'œ'
0, // 157 - ''
0, // 158 - 'ž'
0, // 159 - 'Ÿ'
0, // 160 - ''
0, // 161 - '¡'
0, // 162 - '¢'
0, // 163 - '£'
0, // 164 - '¤'
0, // 165 - '¥'
0, // 166 - '¦'
0, // 167 - '§'
0, // 168 - '¨'
8, 224, 224, 0, 0, 0, 0, 0, 0, // 169 - '©'
8, 224, 224, 0, 252, 252, 0, 0, 0, // 170 - 'ª'
8, 224, 224, 0, 252, 252, 0, 255, 255, // 171 - '«'
0, // 172 - '¬'
0, // 173 - '­'
5, 64, 0, 0, 0, 0, // 174 - '®'
5, 64, 0, 64, 0, 0, // 175 - '¯'
5, 64, 0, 64, 0, 64, // 176 - '°'
6, 254, 146, 146, 146, 254, 0, // 177 - '±'
7, 128, 126, 42, 42, 170, 254, 0, // 178 - '²'
8, 128, 152, 64, 62, 80, 136, 128, 0, // 179 - '³'
8, 72, 40, 152, 254, 16, 40, 68, 0, // 180 - '´'
8, 68, 36, 20, 254, 20, 36, 68, 0, // 181 - 'µ'
8, 168, 232, 172, 250, 172, 232, 168, 0, // 182 - '¶'
8, 128, 136, 136, 254, 136, 136, 128, 0, // 183 - '·'
0, // 184 - '¸'
0, // 185 - '¹'
3, 4, 10, 4, // 186 - 'º'
0, // 187 - '»'
0, // 188 - '¼'
0, // 189 - '½'
0, // 190 - '¾'
0, // 191 - '¿'
0, // 192 - 'À'
0, // 193 - 'Á'
0, // 194 - 'Â'
0, // 195 - 'Ã'
0, // 196 - 'Ä'
0, // 197 - 'Å'
0, // 198 - 'Æ'
0, // 199 - 'Ç'
0, // 200 - 'È'
0, // 201 - 'É'
0, // 202 - 'Ê'
0, // 203 - 'Ë'
0, // 204 - 'Ì'
0, // 205 - 'Í'
0, // 206 - 'Î'
0, // 207 - 'Ï'
0, // 208 - 'Ð'
0, // 209 - 'Ñ'
0, // 210 - 'Ò'
0, // 211 - 'Ó'
0, // 212 - 'Ô'
0, // 213 - 'Õ'
0, // 214 - 'Ö'
0, // 215 - '×'
0, // 216 - 'Ø'
0, // 217 - 'Ù'
0, // 218 - 'Ú'
0, // 219 - 'Û'
0, // 220 - 'Ü'
0, // 221 - 'Ý'
0, // 222 - 'Þ'
0, // 223 - 'ß'
0, // 224 - 'à'
0, // 225 - 'á'
0, // 226 - 'â'
0, // 227 - 'ã'
0, // 228 - 'ä'
0, // 229 - 'å'
0, // 230 - 'æ'
0, // 231 - 'ç'
0, // 232 - 'è'
0, // 233 - 'é'
0, // 234 - 'ê'
0, // 235 - 'ë'
0, // 236 - 'ì'
0, // 237 - 'í'
0, // 238 - 'î'
0, // 239 - 'ï'
0, // 240 - 'ð'
0, // 241 - 'ñ'
0, // 242 - 'ò'
0, // 243 - 'ó'
0, // 244 - 'ô'
0, // 245 - 'õ'
0, // 246 - 'ö'
0, // 247 - '÷'
0, // 248 - 'ø'
0, // 249 - 'ù'
0, // 250 - 'ú'
0, // 251 - 'û'
0, // 252 - 'ü'
0, // 253 - 'ý'
0, // 254 - 'þ'
0, // 255 - 'ÿ'
};