Finalize Scripture of the Day code

This commit is contained in:
ChNussbaum 2020-11-19 16:41:08 -06:00
parent a160abeee4
commit c4ea5150cc
9 changed files with 247 additions and 45 deletions

1
.gitignore vendored
View File

@ -5,5 +5,6 @@
**/.piolibdeps/
**/lib/
**/src/
/build/
**/platformio.ini
/secrets.yaml

View File

@ -31,8 +31,8 @@
> ### [Pool Pumps](./devices/pool_pumps.yaml)
> This is a [Shelly 2.5 Double Relay Switch](https://www.amazon.com/gp/product/B07RRD13DJ/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1) that is controlling the main pump on my pool and the auxillary pump that runs the pool cleaner. It turns the pump on and off through out the day and off at night (when we are least likely to be using the pool and when you get the most heat/water loss if the pump is running) and turns on the cleaner for a couple of hours in the morning. It also has some modes for Off (during the winter) and Continous when I need extra cleaning.
> ### [Scripture of the Day](./devices/scripture_of_the_day.yaml)
> This is a project I just started working on (and I am still waiting on the hardware to arrive from China). I am planning on building 2 of them as Christmas presents for my wife and son. It will consist of a [ESP8266 e-Paper Panel Driver Board](https://www.waveshare.com/e-paper-esp8266-driver-board.htm) powered by a [lithium battery](https://www.amazon.com/dp/B0867KDMY7/?coliid=IE0LBNACFHG4U&colid=1LOK862UA8LA0&psc=1&ref_=lv_ov_lig_dp_it) and [TP4056 lithium battery charger module](https://www.amazon.com/dp/B06XQRQR3Q/?coliid=I1B2ELKKLLKAK0&colid=1LOK862UA8LA0&psc=1&ref_=lv_ov_lig_dp_it) and driving a [Waveshare 7.5inch 800×480 E-Ink display](https://www.waveshare.com/7.5inch-e-paper.htm) all mounted inside a picture frame. The plan is to have it sit in deep-sleep most of the time but wake up every night, grab a random scripture from the [Our Manna Daily Verses API](http://www.ourmanna.com/verses/api/), update the display with the verse, and go back to sleep.
> ### [Scripture of the Day Melissa](./devices/scripture_of_the_day_melissa.yaml)/[Scripture of the Day Mayson](./devices/scripture_of_the_day_mayson.yaml)
> This is a project I just started working on recently, the code is complete but the build is not quite done. I am planning on building 2 of them as Christmas presents for my wife and son. It will consist of a [ESP32 e-Paper Panel Driver Board](https://www.waveshare.com/product/displays/e-paper-esp32-driver-board.htm) powered by a [lithium battery](https://www.amazon.com/dp/B0867KDMY7/?coliid=IE0LBNACFHG4U&colid=1LOK862UA8LA0&psc=1&ref_=lv_ov_lig_dp_it) and [TP4056 lithium battery charger module](https://www.amazon.com/dp/B06XQRQR3Q/?coliid=I1B2ELKKLLKAK0&colid=1LOK862UA8LA0&psc=1&ref_=lv_ov_lig_dp_it) and driving a [Waveshare 7.5inch 800×480 E-Ink display](https://www.waveshare.com/7.5inch-e-paper.htm) all mounted inside a wood frame I am building. The plan is to have it sit in deep-sleep most of the time but wake up every night, grab a random scripture from the [Our Manna Daily Verses API](http://www.ourmanna.com/verses/api/), update the display with the verse, and go back to sleep.
## Switches
> I plan to use dimmer switches for anything that is dimmable just for consistency and you never know when you might want to have the ability to dim a light. However there are times when a dimmer isn't an option.

View File

@ -0,0 +1,9 @@
wifi:
ssid: ${wifi_ssid}
password: ${wifi_password}
fast_connect: true
power_save_mode: none
ap:
ssid: ${device_id}
captive_portal:

View File

@ -0,0 +1,146 @@
#include "esphome.h"
#include <ArduinoJson.h>
#include <sstream>
using namespace esphome;
#define SCRIPTURE_URL "http://beta.ourmanna.com/api/v1/get/?format=json&order=random"
#define MAX_VERSE_LINES 8
#define MAX_CHAR_PER_LINE 35
#define STARTING_POSITION 40
#define SPACE_BETWEEN_LINES 50
#define JSON_BUFFER_SIZE (JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(1))
class ScriptureOfTheDay : public Component {
public:
float get_setup_priority() const override { return setup_priority::LATE; }
void setup() override { update_at_ = millis() + 4000; }
void loop() override;
void set_http_request(http_request::HttpRequestComponent *http_request) { http_request_ = http_request; }
void set_display(waveshare_epaper::WaveshareEPaper *display) { display_ = display; }
void set_deep_sleep(deep_sleep::DeepSleepComponent *deep_sleep) { deep_sleep_ = deep_sleep; }
void set_sntp(sntp::SNTPComponent *sntp) { sntp_ = sntp; }
void set_fonts(display::Font *verse_font, display::Font *reference_font) { verse_font_ = verse_font; reference_font_ = reference_font; }
void display_scripture();
protected:
http_request::HttpRequestComponent *http_request_;
waveshare_epaper::WaveshareEPaper *display_;
deep_sleep::DeepSleepComponent *deep_sleep_;
sntp::SNTPComponent *sntp_;
display::Font *verse_font_;
display::Font *reference_font_;
std::vector<std::string> scripture_;
uint64_t update_at_;
std::vector<std::string> get_scripture();
std::vector<std::string> split_verse_into_lines(std::string verse);
void shutdown(uint32_t sleepSeconds = 0);
};
void ScriptureOfTheDay::loop()
{
// If we try to make the request to soon it fails so we delay 4 seconds
if (millis() > update_at_)
{
// If we get an especially long verse that won't fit on the display we try again.
do
{
scripture_ = get_scripture();
} while (scripture_.size() > MAX_VERSE_LINES + 1);
display_->update();
shutdown();
}
}
void ScriptureOfTheDay::display_scripture()
{
if (scripture_.size() == 0)
{
return;
}
int verseLineCount = scripture_.size() - 1;
int currentPosition = STARTING_POSITION + (SPACE_BETWEEN_LINES / 2) * (MAX_VERSE_LINES - verseLineCount);
for (int i = 0; i < verseLineCount; i++)
{
ESP_LOGD("Nuttytree", scripture_[i].c_str());
display_->print(400, currentPosition, verse_font_, TextAlign::CENTER, scripture_[i].c_str());
currentPosition += SPACE_BETWEEN_LINES;
}
display_->print(760, currentPosition, reference_font_, TextAlign::CENTER_RIGHT, scripture_[verseLineCount].c_str());
}
std::vector<std::string> ScriptureOfTheDay::get_scripture()
{
http_request_->set_url(SCRIPTURE_URL);
http_request_->set_method("GET");
http_request_->send();
if (http_request_->status_has_warning())
{
// If the request failed we shutdown and try again in 15 minutes
shutdown(15 * 60);
}
const char *json = http_request_->get_string();
DynamicJsonBuffer jsonBuffer(JSON_BUFFER_SIZE);
JsonObject& scripture = jsonBuffer.parseObject(json);
http_request_->close();
std::vector<std::string> formattedScripture = split_verse_into_lines(std::string(scripture["verse"]["details"]["text"].as<char*>()));
formattedScripture.push_back(std::string(scripture["verse"]["details"]["reference"].as<char*>()));
return formattedScripture;
}
std::vector<std::string> ScriptureOfTheDay::split_verse_into_lines(std::string verse)
{
std::string word;
std::string currentLine;
std::vector<std::string> lines;
std::istringstream ss(verse);
while (ss >> word)
{
if (currentLine.length() == 0)
{
currentLine = word;
}
else if (currentLine.length() + word.length() < MAX_CHAR_PER_LINE)
{
currentLine += " " + word;
}
else
{
lines.push_back(currentLine);
currentLine = word;
}
}
lines.push_back(currentLine);
return lines;
}
void ScriptureOfTheDay::shutdown(uint32_t sleepSeconds)
{
if (sleepSeconds == 0)
{
// Wake back up and update at 3AM
time::ESPTime now = sntp_->now();
sleepSeconds = 24 * 60 * 60 - (now.hour - 3) * 60 * 60 - now.minute * 60 - now.second;
}
deep_sleep_->set_sleep_duration(sleepSeconds * 1000);
deep_sleep_->begin_sleep(true);
}
ScriptureOfTheDay *Scripture;

10
devices/.gitignore vendored
View File

@ -1,10 +0,0 @@
# Gitignore settings for ESPHome
# This is an example and may include too much for your use-case.
# You can modify this file to suit your needs.
/.esphome/
**/.pioenvs/
**/.piolibdeps/
**/lib/
**/src/
**/platformio.ini
/secrets.yaml

View File

@ -1,33 +0,0 @@
substitutions:
device_id: scripture_of_the_day_1
device_name: Scripture of the Day #1
platform: ESP8266
board: nodemcuv2
ip_address: !secret master_bath_humidity_temp_sensor_ip
ota_pwd: !secret master_bath_humidity_temp_sensor_ota_pwd
api_pwd: !secret master_bath_humidity_temp_sensor_api_pwd
ap_wifi_pwd: !secret master_bath_humidity_temp_sensor_ap_wifi_pwd
esphome:
<<: !include ../core/esphome.yaml
on_boot:
priority: -100
then:
- http_request.get:
url: "https://beta.ourmanna.com/api/v1/get/?format=json&order=random"
verify_ssl: false
- lambda: |-
auto json = http_request_httprequestcomponent->get_string();
<<: !include ../components/logger/logger_debug.yaml
<<: !include ../core/wifi_api_ota.yaml
http_request:
text_sensor:
- platform: template
id: scripture
- platform: template
id: reference

View File

@ -0,0 +1,7 @@
substitutions:
device_id: scripture_of_the_day_mayson
device_name: Scripture of the Day Mayson
log_level: debug
packages:
device_base: !include ../packages/scripture_of_the_day.yaml

View File

@ -0,0 +1,7 @@
substitutions:
device_id: scripture_of_the_day_melissa
device_name: Scripture of the Day Melissa
log_level: debug
packages:
device_base: !include ../packages/scripture_of_the_day.yaml

View File

@ -0,0 +1,75 @@
substitutions:
platform: ESP32
board: esp32dev
log_level: none
wifi_ssid: !secret wifi_ssid
wifi_password: !secret wifi_password
esphome:
name: ${device_id}
platform: ${platform}
board: ${board}
arduino_version: latest
build_path: ../build/${device_id}
includes:
- ../custom/scripture_of_the_day.h
# on_boot:
# priority: -100
# then:
# - delay: 4s
# - lambda: Scripture->update_scripture();
<<: !include ../components/wifi/wifi_dhcp.yaml
<<: !include ../components/logger/logger.yaml
custom_component:
- lambda: |-
Scripture = new ScriptureOfTheDay();
Scripture->set_http_request(http_cmp);
Scripture->set_display(the_display);
Scripture->set_deep_sleep(deep_sleep_cmp);
Scripture->set_sntp(sntp_cmp);
Scripture->set_fonts(verse_font, reference_font);
return {Scripture};
# Setting run duration to 15s, if we aren't done by then something went wrong so we restart to save battery
# Setting a default sleep time of 15min that will only apply if we forced a shutdown after the 15s run duration
deep_sleep:
id: deep_sleep_cmp
run_duration: 15s
sleep_duration: 15min
display:
- platform: waveshare_epaper
id: the_display
cs_pin: 15
dc_pin: 27
busy_pin: 25
reset_pin: 26
update_interval: 600s
model: 7.50inV2
lambda: |-
Scripture->display_scripture();
font:
- file: "c:/windows/fonts/segoeprb.ttf"
id: verse_font
size: 35
glyphs: "~!&-;:\"',.?—“”0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz"
- file: "c:/windows/fonts/segoeprb.ttf"
id: reference_font
size: 30
glyphs: "-:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz"
http_request:
id: http_cmp
spi:
clk_pin: 13
mosi_pin: 14
time:
- platform: sntp
id: sntp_cmp
timezone: America/Chicago