mirror of
				https://github.com/Clortox/dashboard.git
				synced 2025-07-17 14:02:10 +00:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "998f3554602c1e67b47ea62a498fca8ae0e7fcba" and "55f68ac3cb0e68150e2f205ca70bba115c1f886b" have entirely different histories.
		
	
	
		
			998f355460
			...
			55f68ac3cb
		
	
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -13,6 +13,3 @@ src/config.hpp
 | 
			
		||||
 | 
			
		||||
#ignore wifi image
 | 
			
		||||
img/wifi.png
 | 
			
		||||
 | 
			
		||||
#ignore json in tests
 | 
			
		||||
tests/*.json
 | 
			
		||||
 | 
			
		||||
@ -66,10 +66,3 @@ Things you need to implement as a panel creator
 | 
			
		||||
- `const_resources`
 | 
			
		||||
 | 
			
		||||
And be sure to inheret from dashboard::panel !
 | 
			
		||||
 | 
			
		||||
FAQ
 | 
			
		||||
===
 | 
			
		||||
 | 
			
		||||
- I wrote my pannel, yet i keep seeing that SCREEN_WIDTH, SCREEN_HEIGHT,
 | 
			
		||||
  board::*, etc are not defined 
 | 
			
		||||
  - Be sure to add `#include "../board.hpp"` at the end of your mypanel.hpp
 | 
			
		||||
 | 
			
		||||
@ -2,21 +2,20 @@ dashboard
 | 
			
		||||
=========
 | 
			
		||||
 | 
			
		||||
My dashboard, for my house. Display RSS feeds and other custom bits of info via
 | 
			
		||||
direct SDL2 calls.
 | 
			
		||||
direct SDL2 calls. 
 | 
			
		||||
 | 
			
		||||
Features/TODO
 | 
			
		||||
=============
 | 
			
		||||
 | 
			
		||||
- (DONE) Write straight to framebuffer (sdl2)
 | 
			
		||||
- (DONE) Write straight to framebuffer (sdl2) 
 | 
			
		||||
- (DONE) Display Weather ~~rss~~ json feed
 | 
			
		||||
  - Get UV Data from openUV
 | 
			
		||||
- (DONE) Display Wifi qrcode
 | 
			
		||||
- (DONE) Display Wifi qrcode 
 | 
			
		||||
  - Get wifispeed and number of clients from home assistant
 | 
			
		||||
- (DONE) Display plex currently playing
 | 
			
		||||
- Display camera feed
 | 
			
		||||
- Integrate with Home assistant data (New panel)
 | 
			
		||||
- Integrate with Home assistant data (New panel) 
 | 
			
		||||
  - https://developers.home-assistant.io/docs/api/rest/
 | 
			
		||||
  - (DONE) Presence
 | 
			
		||||
- Integrate with octoprint
 | 
			
		||||
 | 
			
		||||
Depends on
 | 
			
		||||
 | 
			
		||||
@ -10,12 +10,10 @@
 | 
			
		||||
// A list of all panels to be displayed, in order
 | 
			
		||||
dashboard::panel::panel* PANELS[] = {
 | 
			
		||||
    //new dashboard::panel::sample_panel(),
 | 
			
		||||
    new dashboard::panel::homeassistant(),
 | 
			
		||||
    new dashboard::panel::plex(),
 | 
			
		||||
    new dashboard::panel::weather(),
 | 
			
		||||
    new dashboard::panel::wifi(),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
size_t PANELS_LENGTH = sizeof(PANELS)/sizeof(PANELS[0]);
 | 
			
		||||
 | 
			
		||||
// OVERLAY
 | 
			
		||||
@ -51,8 +49,7 @@ const char* IMAGE_LOCATIONS[] = {
 | 
			
		||||
 | 
			
		||||
    //plex
 | 
			
		||||
    "plex_background.jpg",
 | 
			
		||||
 | 
			
		||||
    //homeassistant
 | 
			
		||||
    
 | 
			
		||||
};
 | 
			
		||||
size_t IMAGE_LOCATIONS_LENGTH = sizeof(IMAGE_LOCATIONS)/sizeof(IMAGE_LOCATIONS[0]);
 | 
			
		||||
 | 
			
		||||
@ -79,7 +76,6 @@ const FONT_SIZE_STRING CONST_STRINGS[] = {
 | 
			
		||||
    { "Weather", { "Roboto_Mono/RobotoMono-Medium.ttf", 50 } },
 | 
			
		||||
    { "Wireless", { "Roboto_Mono/RobotoMono-Medium.ttf", 50 } },
 | 
			
		||||
    { "Plex", { "Roboto_Mono/RobotoMono-Medium.ttf", 50} },
 | 
			
		||||
    { "Homeassistant", { "Roboto_Mono/RobotoMono-Medium.ttf", 50} },
 | 
			
		||||
    //sample panel
 | 
			
		||||
    //{ "Sample Panel", { "Roboto_Mono/RobotoMono-Medium.ttf", 50} },
 | 
			
		||||
 | 
			
		||||
@ -105,7 +101,5 @@ const FONT_SIZE_STRING CONST_STRINGS[] = {
 | 
			
		||||
    { "Playing", {"Roboto_Mono/RobotoMono-Medium.ttf", 28} },
 | 
			
		||||
    { "Top Users", {"Roboto_Mono/RobotoMono-Medium.ttf", 50} },
 | 
			
		||||
 | 
			
		||||
    //Home assistant
 | 
			
		||||
    { "Home", {"Roboto_Mono/RobotoMono-Medium.ttf", 50} },
 | 
			
		||||
};
 | 
			
		||||
size_t CONST_STRINGS_LENGTH = sizeof(CONST_STRINGS)/sizeof(CONST_STRINGS[0]);
 | 
			
		||||
 | 
			
		||||
@ -79,7 +79,6 @@ constexpr int IMG_FLAGS = 0
 | 
			
		||||
#include "panel/def_overlay.hpp"
 | 
			
		||||
#include "panel/wifi.hpp"
 | 
			
		||||
#include "panel/plex.hpp"
 | 
			
		||||
#include "panel/homeassistant.hpp"
 | 
			
		||||
//uncomment this to use the sample panel
 | 
			
		||||
//#include "panel/sample_panel.hpp"
 | 
			
		||||
extern dashboard::panel::panel* PANELS[];
 | 
			
		||||
 | 
			
		||||
@ -16,7 +16,7 @@ int main(int argc, char** argv){
 | 
			
		||||
    dashboard::board _board(false);
 | 
			
		||||
 | 
			
		||||
    if(_board.init() != 0){
 | 
			
		||||
        std::cerr << "Due to errors, " << argv[0]
 | 
			
		||||
        std::cerr << "Due to errors, " << argv[0] 
 | 
			
		||||
            << " was unable to start, quitting!" << std::endl;
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,223 +0,0 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Tyler Perkins
 | 
			
		||||
// 14-1-22
 | 
			
		||||
// homeassistant panel
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include "homeassistant.hpp"
 | 
			
		||||
#include "homeassistant_config.hpp"
 | 
			
		||||
 | 
			
		||||
using namespace dashboard::panel;
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Constructors ///////////////////////////////////////////////////////////////
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
homeassistant::homeassistant(){
 | 
			
		||||
    std::cerr << "HOMEASSISTANT CONSTRUCTOR\n";
 | 
			
		||||
    _time_on_screen = HOMEASSISTANT_DEFAULT_ON_SCREEN_TIME;
 | 
			
		||||
    _update_interval = std::chrono::milliseconds{HOMEASSISTANT_UPDATE_INTERVAL};
 | 
			
		||||
    _texture = nullptr;
 | 
			
		||||
    _title = HOMEASSISTANT_TITLE;
 | 
			
		||||
 | 
			
		||||
    std::string api_string = "Authorization: Bearer ";
 | 
			
		||||
    api_string += HOMEASSISTANT_APIKEY;
 | 
			
		||||
 | 
			
		||||
    headers = NULL;
 | 
			
		||||
    headers = curl_slist_append(headers, api_string.c_str());
 | 
			
		||||
    headers = curl_slist_append(headers, "Content-Type: application/json");
 | 
			
		||||
 | 
			
		||||
    api_string.clear();
 | 
			
		||||
 | 
			
		||||
    api_curl = curl_easy_init();
 | 
			
		||||
    curl_easy_setopt(api_curl, CURLOPT_HTTPHEADER, headers);
 | 
			
		||||
    curl_easy_setopt(api_curl, CURLOPT_URL, HOMEASSISTANT_URL);
 | 
			
		||||
    curl_easy_setopt(api_curl, CURLOPT_WRITEFUNCTION,
 | 
			
		||||
            dashboard::panel::homeassistant::curl_callback);
 | 
			
		||||
    curl_easy_setopt(api_curl, CURLOPT_WRITEDATA, &json_string);
 | 
			
		||||
    //Write request string in update function
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
homeassistant::~homeassistant(){
 | 
			
		||||
    std::cerr << "HOMEASSISTANT DECONSTRUCTOR\n";
 | 
			
		||||
    if(_texture != nullptr){
 | 
			
		||||
        SDL_DestroyTexture(_texture);
 | 
			
		||||
    }
 | 
			
		||||
    if(api_curl != nullptr){
 | 
			
		||||
        curl_easy_cleanup(api_curl);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Draw function //////////////////////////////////////////////////////////////
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
void homeassistant::draw(){
 | 
			
		||||
    //create the texture if this is the first time running draw
 | 
			
		||||
    if(_texture == nullptr){
 | 
			
		||||
        initTexture();
 | 
			
		||||
        update();
 | 
			
		||||
        update_texture();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //check if its time to update
 | 
			
		||||
    if((std::chrono::high_resolution_clock::now() - _last_update)
 | 
			
		||||
            > _update_interval){
 | 
			
		||||
        update();
 | 
			
		||||
 | 
			
		||||
        update_texture();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SDL_RenderCopy(board::getRenderer(), _texture, NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Helper functions ///////////////////////////////////////////////////////////
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////
 | 
			
		||||
// Update the information of the obj
 | 
			
		||||
// This DOES NOT update the display
 | 
			
		||||
void homeassistant::update(){
 | 
			
		||||
    std::cerr << "HOMEASSISTANT::UPDATE\n";
 | 
			
		||||
    _last_update = std::chrono::high_resolution_clock::now();
 | 
			
		||||
 | 
			
		||||
    //perform request
 | 
			
		||||
    curl_easy_perform(api_curl);
 | 
			
		||||
 | 
			
		||||
    //parse the result
 | 
			
		||||
    json_doc.Parse(json_string.c_str());
 | 
			
		||||
 | 
			
		||||
    //update internal state
 | 
			
		||||
    for(rapidjson::SizeType i = 0; i < json_doc.Size(); i++){
 | 
			
		||||
 | 
			
		||||
        //if is a person entry
 | 
			
		||||
        if(strstr(json_doc[i]["entity_id"].GetString(), "person.") != NULL){
 | 
			
		||||
            //get the last changed date and convert to a tm
 | 
			
		||||
            std::string format_str = json_doc[i]["last_changed"].GetString();
 | 
			
		||||
            std::time_t t = datestringToTm(format_str);
 | 
			
		||||
            std::stringstream ss;
 | 
			
		||||
            ss << std::put_time(std::localtime(&t), "%b %e, %I:%M %p");
 | 
			
		||||
 | 
			
		||||
            struct home_entry entry = {
 | 
			
		||||
                json_doc[i]["attributes"]["friendly_name"].GetString(),
 | 
			
		||||
                strcmp(json_doc[i]["state"].GetString(), "home") == 0 ? true : false,
 | 
			
		||||
                ss.str(),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            home_entries.push_back(entry);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //TODO other entries from general home assistant?
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    json_string.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////
 | 
			
		||||
// Update the texture that is being
 | 
			
		||||
// displayed, based on data grabed from json
 | 
			
		||||
void homeassistant::update_texture(){
 | 
			
		||||
    std::cerr << "HOMEASSISTANT::UPDATE_TEXTURE\n";
 | 
			
		||||
 | 
			
		||||
    SDL_Rect tgt;
 | 
			
		||||
 | 
			
		||||
    SDL_SetRenderTarget(board::getRenderer(), _texture);
 | 
			
		||||
    SDL_RenderClear(board::getRenderer());
 | 
			
		||||
 | 
			
		||||
    constexpr int GAP_SIZE = 10;
 | 
			
		||||
 | 
			
		||||
    //draw each name and time last seen
 | 
			
		||||
    {
 | 
			
		||||
        for(size_t i = 0; i < home_entries.size(); ++i){
 | 
			
		||||
            tgt.x = (SCREEN_WIDTH / (2 * home_entries.size()))
 | 
			
		||||
                + i * (SCREEN_WIDTH / home_entries.size());
 | 
			
		||||
            tgt.y = DEF_OVERLAY_BAR_HEIGHT + GAP_SIZE;
 | 
			
		||||
            TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 50} ),
 | 
			
		||||
                    home_entries[i].name.c_str(),
 | 
			
		||||
                    &tgt.w, &tgt.h);
 | 
			
		||||
 | 
			
		||||
            tgt.x -= tgt.w / 2;
 | 
			
		||||
 | 
			
		||||
            SDL_RenderCopy(board::getRenderer(),
 | 
			
		||||
                    board::getString(home_entries[i].name,
 | 
			
		||||
                    { "Roboto_Mono/RobotoMono-Medium.ttf", 50 }),
 | 
			
		||||
                NULL, &tgt);
 | 
			
		||||
 | 
			
		||||
            //down a new line
 | 
			
		||||
            tgt.y += tgt.h + GAP_SIZE;
 | 
			
		||||
            tgt.x += tgt.w / 2;
 | 
			
		||||
 | 
			
		||||
            std::string home = "";
 | 
			
		||||
 | 
			
		||||
            //if is home
 | 
			
		||||
            if(home_entries[i].home){
 | 
			
		||||
                home = "Home";
 | 
			
		||||
            } else {
 | 
			
		||||
                home = home_entries[i].time;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 50} ),
 | 
			
		||||
                home.c_str(),
 | 
			
		||||
                &tgt.w, &tgt.h);
 | 
			
		||||
 | 
			
		||||
            tgt.x -= tgt.w / 2;
 | 
			
		||||
 | 
			
		||||
            SDL_RenderCopy(board::getRenderer(),
 | 
			
		||||
                    board::getString(home,
 | 
			
		||||
                    { "Roboto_Mono/RobotoMono-Medium.ttf", 50 }),
 | 
			
		||||
                    NULL, &tgt);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    home_entries.clear();
 | 
			
		||||
    SDL_SetRenderTarget(board::getRenderer(), NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////
 | 
			
		||||
// Lazy load the texture object
 | 
			
		||||
// This is to make sure that all of SDL
 | 
			
		||||
// is init before we attempt to draw anything
 | 
			
		||||
void homeassistant::initTexture(){
 | 
			
		||||
    if(_texture == nullptr){
 | 
			
		||||
        _texture = SDL_CreateTexture(board::getRenderer(),
 | 
			
		||||
                SDL_PIXELFORMAT_RGBA8888,
 | 
			
		||||
                SDL_TEXTUREACCESS_TARGET,
 | 
			
		||||
                SCREEN_WIDTH, SCREEN_HEIGHT);
 | 
			
		||||
 | 
			
		||||
        SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_BLEND);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////
 | 
			
		||||
// Convert the homeassistant string
 | 
			
		||||
// format to a tm object
 | 
			
		||||
std::time_t homeassistant::datestringToTm(const std::string& date_string){
 | 
			
		||||
    int year = 0, month = 0, day = 0, hour = 0, minuite = 0, second = 0;
 | 
			
		||||
 | 
			
		||||
    std::tm tm_tmp{};
 | 
			
		||||
 | 
			
		||||
    if(sscanf(date_string.c_str(), "%4d-%2d-%2dT%2d:%2d:%2d",
 | 
			
		||||
                &year, &month, &day, &hour, &minuite, &second) == 6){
 | 
			
		||||
        tm_tmp.tm_year = year - 1900;
 | 
			
		||||
        tm_tmp.tm_mon = month - 1;
 | 
			
		||||
        tm_tmp.tm_mday = day;
 | 
			
		||||
        tm_tmp.tm_hour = hour;
 | 
			
		||||
        tm_tmp.tm_min = minuite;
 | 
			
		||||
        tm_tmp.tm_sec = second;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return std::mktime(&tm_tmp) - timezone;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////
 | 
			
		||||
// Curl callback function
 | 
			
		||||
size_t dashboard::panel::homeassistant::curl_callback(void* contents, size_t size,
 | 
			
		||||
        size_t nmemb, void* userp){
 | 
			
		||||
    ((std::string*)userp)->append((char*)contents, size * nmemb);
 | 
			
		||||
    return size * nmemb;
 | 
			
		||||
}
 | 
			
		||||
@ -1,59 +0,0 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Tyler Perkins
 | 
			
		||||
// 14-1-22
 | 
			
		||||
// Home assistant panel
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "panel.hpp"
 | 
			
		||||
 | 
			
		||||
#include <SDL.h>
 | 
			
		||||
#include <SDL2/SDL_image.h>
 | 
			
		||||
#include <SDL2/SDL_ttf.h>
 | 
			
		||||
 | 
			
		||||
#include <curl/curl.h>
 | 
			
		||||
#include "../util/rapidjson/document.h"
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <iomanip>
 | 
			
		||||
 | 
			
		||||
namespace dashboard::panel {
 | 
			
		||||
    class homeassistant : public panel {
 | 
			
		||||
    public:
 | 
			
		||||
        homeassistant();
 | 
			
		||||
        ~homeassistant();
 | 
			
		||||
 | 
			
		||||
        static size_t curl_callback(void*, size_t, size_t, void*);
 | 
			
		||||
 | 
			
		||||
        void draw();
 | 
			
		||||
    private:
 | 
			
		||||
        void update();
 | 
			
		||||
        void update_texture();
 | 
			
		||||
        void initTexture();
 | 
			
		||||
 | 
			
		||||
        std::time_t datestringToTm(const std::string&);
 | 
			
		||||
 | 
			
		||||
        struct home_entry {
 | 
			
		||||
            std::string name;
 | 
			
		||||
            bool home;
 | 
			
		||||
            std::string time;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        std::vector<home_entry> home_entries;
 | 
			
		||||
 | 
			
		||||
        CURL* api_curl;
 | 
			
		||||
        struct curl_slist *headers;
 | 
			
		||||
        std::string json_string;
 | 
			
		||||
        rapidjson::Document json_doc;
 | 
			
		||||
 | 
			
		||||
        std::chrono::time_point<std::chrono::high_resolution_clock> _last_update;
 | 
			
		||||
        std::chrono::milliseconds _update_interval;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#include "../board.hpp"
 | 
			
		||||
@ -1,31 +0,0 @@
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
// Tyler Perkins
 | 
			
		||||
// 14-1-22
 | 
			
		||||
// homeassistant configuration
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "def_overlay_config.hpp"
 | 
			
		||||
 | 
			
		||||
namespace dashboard::panel {
 | 
			
		||||
    //This will be displayed at the top left on the status bar. Set to a blank
 | 
			
		||||
    //string to not show anything
 | 
			
		||||
    constexpr char HOMEASSISTANT_TITLE[] = "Home assistant";
 | 
			
		||||
 | 
			
		||||
    //API key, you can get this in homeassistant under your profile
 | 
			
		||||
    constexpr char HOMEASSISTANT_APIKEY[] = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxYTNhNDhhYTBlZDM0MjkyOTk5OWZhNGVjZGRjMGUwMCIsImlhdCI6MTY0MjE4NDU0MCwiZXhwIjoxOTU3NTQ0NTQwfQ.Zdy7-ZwX0HuwhmUGeLhF5XCluotsKmpDqmi5o-hQZCc";
 | 
			
		||||
 | 
			
		||||
    //This API endpoint. Sub the IP with the IP of the homeassistant server on
 | 
			
		||||
    //your network. Be sure to enable the RESTful API in homeassistant's
 | 
			
		||||
    //configuration.yaml
 | 
			
		||||
    constexpr char HOMEASSISTANT_URL[] = "http://192.168.1.104:8123/api/states";
 | 
			
		||||
 | 
			
		||||
    //Default time the slide is shown on screen, in ms
 | 
			
		||||
    //Default 15s
 | 
			
		||||
    constexpr size_t HOMEASSISTANT_DEFAULT_ON_SCREEN_TIME = 15000;
 | 
			
		||||
 | 
			
		||||
    //How long should we wait between updates? in ms
 | 
			
		||||
    //Default 15
 | 
			
		||||
    constexpr size_t HOMEASSISTANT_UPDATE_INTERVAL = 15000;
 | 
			
		||||
}
 | 
			
		||||
@ -50,7 +50,7 @@ void plex::draw(){
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //check if its time to update
 | 
			
		||||
    if((std::chrono::high_resolution_clock::now() - _last_update)
 | 
			
		||||
    if((std::chrono::high_resolution_clock::now() - _last_update) 
 | 
			
		||||
            > _update_interval){
 | 
			
		||||
        update();
 | 
			
		||||
 | 
			
		||||
@ -84,13 +84,13 @@ void plex::update(){
 | 
			
		||||
 | 
			
		||||
    for(short i = 0; i < 4; ++i){
 | 
			
		||||
        entries.at(i) = {
 | 
			
		||||
            truncate(curr_entry[i]["friendly_name"].GetString(),
 | 
			
		||||
            truncate(curr_entry[i]["friendly_name"].GetString(), 
 | 
			
		||||
                    PLEX_MAX_STRING_LENGTH),
 | 
			
		||||
            truncate(curr_entry[i]["ip_address"].GetString(),
 | 
			
		||||
            truncate(curr_entry[i]["ip_address"].GetString(), 
 | 
			
		||||
                    PLEX_MAX_STRING_LENGTH),
 | 
			
		||||
            truncate(curr_entry[i]["title"].GetString(),
 | 
			
		||||
            truncate(curr_entry[i]["title"].GetString(), 
 | 
			
		||||
                    PLEX_MAX_STRING_LENGTH),
 | 
			
		||||
            truncate(curr_entry[i]["state"].IsNull() ? "Historical" : "Playing",
 | 
			
		||||
            truncate(curr_entry[i]["state"].IsNull() ? "Historical" : "Playing", 
 | 
			
		||||
                    PLEX_MAX_STRING_LENGTH),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
@ -129,7 +129,7 @@ void plex::update(){
 | 
			
		||||
    json_doc.Parse(json_string.c_str());
 | 
			
		||||
 | 
			
		||||
    friendly_name = truncate(json_doc["response"]["data"].GetString(), PLEX_MAX_STRING_LENGTH - 10);
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    json_string.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -144,13 +144,13 @@ void plex::update_texture(){
 | 
			
		||||
    //save the old colors
 | 
			
		||||
    SDL_GetRenderDrawColor(board::getRenderer(), &o_red,
 | 
			
		||||
            &o_green, &o_blue, &o_alpha);
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    SDL_SetRenderTarget(board::getRenderer(), _texture);
 | 
			
		||||
    SDL_RenderClear(board::getRenderer());
 | 
			
		||||
 | 
			
		||||
    //set the new color
 | 
			
		||||
    SDL_SetRenderDrawColor(board::getRenderer(),
 | 
			
		||||
            PLEX_BGBOX_RED, PLEX_BGBOX_GREEN,
 | 
			
		||||
            PLEX_BGBOX_RED, PLEX_BGBOX_GREEN, 
 | 
			
		||||
            PLEX_BGBOX_BLUE, PLEX_BGBOX_ALPHA);
 | 
			
		||||
 | 
			
		||||
    //background image
 | 
			
		||||
@ -411,8 +411,8 @@ void plex::update_texture(){
 | 
			
		||||
void plex::initTexture(){
 | 
			
		||||
    if(_texture == nullptr){
 | 
			
		||||
        _texture = SDL_CreateTexture(board::getRenderer(),
 | 
			
		||||
                SDL_PIXELFORMAT_RGBA8888,
 | 
			
		||||
                SDL_TEXTUREACCESS_TARGET,
 | 
			
		||||
                SDL_PIXELFORMAT_RGBA8888, 
 | 
			
		||||
                SDL_TEXTUREACCESS_TARGET, 
 | 
			
		||||
                SCREEN_WIDTH, SCREEN_HEIGHT);
 | 
			
		||||
 | 
			
		||||
        SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_BLEND);
 | 
			
		||||
 | 
			
		||||
@ -39,6 +39,7 @@ namespace dashboard::panel {
 | 
			
		||||
        CURL* api_curl;
 | 
			
		||||
        std::string json_string;
 | 
			
		||||
        rapidjson::Document json_doc;
 | 
			
		||||
 | 
			
		||||
        struct plex_entry {
 | 
			
		||||
            std::string friendly_name;
 | 
			
		||||
            std::string ip_address;
 | 
			
		||||
 | 
			
		||||
@ -13,10 +13,10 @@ namespace dashboard::panel {
 | 
			
		||||
    //string to not show anything
 | 
			
		||||
    constexpr char PLEX_TITLE[] = "Plex";
 | 
			
		||||
 | 
			
		||||
    //Tautili endpoint
 | 
			
		||||
    constexpr char PLEX_URL_SOURCE_HISTORY[] = "http://192.168.1.104:8181/api/v2?apikey=62917cc0bea04aa69cbb85141e312e84&cmd=get_history&length=5";
 | 
			
		||||
    constexpr char PLEX_URL_SOURCE_NAME[] = "http://192.168.1.104:8181/api/v2?apikey=62917cc0bea04aa69cbb85141e312e84&cmd=get_server_friendly_name";
 | 
			
		||||
    constexpr char PLEX_URL_SOURCE_TOP_USERS[] = "http://192.168.1.104:8181/api/v2?apikey=62917cc0bea04aa69cbb85141e312e84&cmd=get_plays_by_top_10_users";
 | 
			
		||||
    //Tautili endpoint 
 | 
			
		||||
    constexpr char PLEX_URL_SOURCE_HISTORY[] = "http://192.168.1.104:8181/api/v2?apikey=64af06e0497342f7a5862462ddbbd309&cmd=get_history&length=5";
 | 
			
		||||
    constexpr char PLEX_URL_SOURCE_NAME[] = "http://192.168.1.104:8181/api/v2?apikey=64af06e0497342f7a5862462ddbbd309&cmd=get_server_friendly_name";
 | 
			
		||||
    constexpr char PLEX_URL_SOURCE_TOP_USERS[] = "http://192.168.1.104:8181/api/v2?apikey=64af06e0497342f7a5862462ddbbd309&cmd=get_plays_by_top_10_users";
 | 
			
		||||
 | 
			
		||||
    //How many characters of a show title should we show?
 | 
			
		||||
    constexpr size_t PLEX_MAX_STRING_LENGTH = 35;
 | 
			
		||||
@ -34,4 +34,5 @@ namespace dashboard::panel {
 | 
			
		||||
    constexpr uint8_t PLEX_BGBOX_GREEN   = 0x66;
 | 
			
		||||
    constexpr uint8_t PLEX_BGBOX_BLUE    = 0x66;
 | 
			
		||||
    constexpr uint8_t PLEX_BGBOX_ALPHA   = 0x99;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -36,57 +36,57 @@ namespace dashboard::panel {
 | 
			
		||||
    //with weather string being the string shown on screen, and weather image
 | 
			
		||||
    //being the name of the preloaded image file to be shown. It is best that
 | 
			
		||||
    //these images be square.
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_CLEAR_DAY =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_CLEAR_DAY = 
 | 
			
		||||
        {"Clear skies", "clearday.png"};
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_CLEAR_NIGHT =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_CLEAR_NIGHT = 
 | 
			
		||||
        {"Clear skies", "clearnight.png"};
 | 
			
		||||
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_PCLOUDY_DAY =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_PCLOUDY_DAY = 
 | 
			
		||||
        {"Slightly cloudy", "cloudyday.png"};
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_PCLOUDY_NIGHT =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_PCLOUDY_NIGHT = 
 | 
			
		||||
        {"Slightly cloudy", "cloudynight.png"};
 | 
			
		||||
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_MCLOUDY_DAY =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_MCLOUDY_DAY = 
 | 
			
		||||
        {"Moderately cloudy", "cloudyday.png"};
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_MCLOUDY_NIGHT =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_MCLOUDY_NIGHT = 
 | 
			
		||||
        {"Moderately cloudy", "cloudynight.png"};
 | 
			
		||||
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_CLOUDY_DAY =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_CLOUDY_DAY = 
 | 
			
		||||
        {"Very cloudy", "cloudyday.png"};
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_CLOUDY_NIGHT =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_CLOUDY_NIGHT = 
 | 
			
		||||
        {"Very cloudy", "cloudynight.png"};
 | 
			
		||||
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_HUMID_DAY =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_HUMID_DAY = 
 | 
			
		||||
        {"Very humid", "humidday.png"};
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_HUMID_NIGHT =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_HUMID_NIGHT = 
 | 
			
		||||
        {"Very humid", "humidnight.png"};
 | 
			
		||||
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_LRAIN_DAY =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_LRAIN_DAY = 
 | 
			
		||||
        {"Light rain", "lrainday.png"};
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_LRAIN_NIGHT =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_LRAIN_NIGHT = 
 | 
			
		||||
        {"Light rain", "lrainnight.png"};
 | 
			
		||||
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_RAIN_DAY =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_RAIN_DAY = 
 | 
			
		||||
        {"Rain", "rainday.png"};
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_RAIN_NIGHT =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_RAIN_NIGHT = 
 | 
			
		||||
        {"Rain", "rainnight.png"};
 | 
			
		||||
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_OSHOWER_DAY =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_OSHOWER_DAY = 
 | 
			
		||||
        {"Overcast with showers", "shower.png"};
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_OSHOWER_NIGHT =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_OSHOWER_NIGHT = 
 | 
			
		||||
        {"Overcast with showers", "shower.png"};
 | 
			
		||||
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_ISHOWER_DAY =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_ISHOWER_DAY = 
 | 
			
		||||
        {"Moderate showers", "shower.png"};
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_ISHOWER_NIGHT =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_ISHOWER_NIGHT = 
 | 
			
		||||
        {"Moderate showers", "shower.png"};
 | 
			
		||||
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_LSNOW_DAY =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_LSNOW_DAY = 
 | 
			
		||||
        {"Light snow", "snowday.png"};
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_LSNOW_NIGHT =
 | 
			
		||||
        {"Light snow", "snownight.png"};
 | 
			
		||||
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_SNOW_DAY =
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_SNOW_DAY = 
 | 
			
		||||
        {"Moderate snow", "snowday.png"};
 | 
			
		||||
    const std::pair<std::string, std::string> WEATHER_SNOW_NIGHT =
 | 
			
		||||
        {"Moderate snow", "snownight.png"};
 | 
			
		||||
 | 
			
		||||
@ -19,21 +19,13 @@ wifi::wifi(){
 | 
			
		||||
    std::cerr << "WIFI CONSTRUCTOR\n";
 | 
			
		||||
    _texture = nullptr;
 | 
			
		||||
    _time_on_screen = WIFI_DEFAULT_TIME_ON_SCREEN;
 | 
			
		||||
    _update_interval = std::chrono::milliseconds{WIFI_UPDATE_INTERVAL};
 | 
			
		||||
    _title = WIFI_TITLE;
 | 
			
		||||
 | 
			
		||||
    api_curl = curl_easy_init();
 | 
			
		||||
    curl_easy_setopt(api_curl, CURLOPT_WRITEFUNCTION,
 | 
			
		||||
            dashboard::panel::wifi::curl_callback);
 | 
			
		||||
    curl_easy_setopt(api_curl, CURLOPT_WRITEDATA, &json_string);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
wifi::~wifi(){
 | 
			
		||||
    std::cerr << "WIFI DECONSTRUCTOR\n";
 | 
			
		||||
    if(_texture != nullptr)
 | 
			
		||||
        SDL_DestroyTexture(_texture);
 | 
			
		||||
    if(api_curl != nullptr)
 | 
			
		||||
        curl_easy_cleanup(api_curl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////////////////////////////////////////////
 | 
			
		||||
@ -48,14 +40,6 @@ void wifi::draw(){
 | 
			
		||||
        update_texture();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //check if its time to update
 | 
			
		||||
    if((std::chrono::high_resolution_clock::now() - _last_update)
 | 
			
		||||
            > _update_interval){
 | 
			
		||||
        update();
 | 
			
		||||
 | 
			
		||||
        update_texture();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SDL_RenderCopy(board::getRenderer(), _texture, NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -67,91 +51,12 @@ void wifi::draw(){
 | 
			
		||||
// Update the information of wifi
 | 
			
		||||
// This DOES NOT update the display
 | 
			
		||||
void wifi::update() {
 | 
			
		||||
    std::cerr << "WIFI::UPDATE\n";
 | 
			
		||||
    _last_update = std::chrono::high_resolution_clock::now();
 | 
			
		||||
 | 
			
		||||
    if(WIFI_HOMEASSISTANT){
 | 
			
		||||
        curl_easy_setopt(api_curl, CURLOPT_URL,
 | 
			
		||||
                WIFI_HOMEASSISTANT_URL);
 | 
			
		||||
        std::string api_string = "Authorization: Bearer ";
 | 
			
		||||
        api_string += WIFI_HOMEASSISTANT_APIKEY;
 | 
			
		||||
 | 
			
		||||
        struct curl_slist *headers;
 | 
			
		||||
        headers = NULL;
 | 
			
		||||
        headers = curl_slist_append(headers, api_string.c_str());
 | 
			
		||||
        headers = curl_slist_append(headers, "Content-Type: application/json");
 | 
			
		||||
 | 
			
		||||
        curl_easy_setopt(api_curl, CURLOPT_HTTPHEADER, headers);
 | 
			
		||||
 | 
			
		||||
        api_string.clear();
 | 
			
		||||
 | 
			
		||||
        //perform request
 | 
			
		||||
        curl_easy_perform(api_curl);
 | 
			
		||||
 | 
			
		||||
        //parse the result
 | 
			
		||||
        json_doc.Parse(json_string.c_str());
 | 
			
		||||
 | 
			
		||||
        //update internal state
 | 
			
		||||
        for(rapidjson::SizeType i = 0; i < json_doc.Size(); i++){
 | 
			
		||||
            //if router external IP
 | 
			
		||||
            if(strcmp(json_doc[i]["entity_id"].GetString(),
 | 
			
		||||
                        WIFI_HOMEASSISTANT_ROUTER_EXTERNAL_IP) == 0
 | 
			
		||||
                    && WIFI_SHOW_PUBLIC_IP){
 | 
			
		||||
                //store it in public IP field
 | 
			
		||||
                public_ip = "WAN IP: ";
 | 
			
		||||
                public_ip += json_doc[i]["state"].GetString();
 | 
			
		||||
            } //if router WAN status
 | 
			
		||||
            else if (strcmp(json_doc[i]["entity_id"].GetString(),
 | 
			
		||||
                        WIFI_HOMEASSISTANT_ROUTER_WAN_STATUS) == 0){
 | 
			
		||||
                if(strcmp(json_doc[i]["state"].GetString(), "Connected") == 0)
 | 
			
		||||
                    wan_status = true;
 | 
			
		||||
                else
 | 
			
		||||
                    wan_status = false;
 | 
			
		||||
            } //speedtest up
 | 
			
		||||
            else if (strcmp(json_doc[i]["entity_id"].GetString(),
 | 
			
		||||
                        WIFI_HOMEASSISTANT_SPEEDTEST_UP) == 0
 | 
			
		||||
                    && WIFI_HOMEASSISTANT_SPEEDTEST){
 | 
			
		||||
                speedtest_up = "Upload: ";
 | 
			
		||||
                speedtest_up += json_doc[i]["state"].GetString();
 | 
			
		||||
                speedtest_up += "Mbps";
 | 
			
		||||
            } //speedtest down
 | 
			
		||||
            else if (strcmp(json_doc[i]["entity_id"].GetString(),
 | 
			
		||||
                        WIFI_HOMEASSISTANT_SPEEDTEST_DOWN) == 0
 | 
			
		||||
                    && WIFI_HOMEASSISTANT_SPEEDTEST){
 | 
			
		||||
                speedtest_down = "Download: ";
 | 
			
		||||
                speedtest_down += json_doc[i]["state"].GetString();
 | 
			
		||||
                speedtest_down += "Mbps";
 | 
			
		||||
            } //speedtest ping
 | 
			
		||||
            else if (strcmp(json_doc[i]["entity_id"].GetString(),
 | 
			
		||||
                        WIFI_HOMEASSISTANT_SPEEDTEST_PING) == 0
 | 
			
		||||
                    && WIFI_HOMEASSISTANT_SPEEDTEST){
 | 
			
		||||
                speedtest_ping = "Ping: ";
 | 
			
		||||
                speedtest_ping += json_doc[i]["state"].GetString();
 | 
			
		||||
                speedtest_ping += "ms";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //if not using home assistant, grab it via normal method
 | 
			
		||||
    if(WIFI_SHOW_PUBLIC_IP){
 | 
			
		||||
        //get the string from normal url
 | 
			
		||||
        if(!WIFI_HOMEASSISTANT){
 | 
			
		||||
            public_ip = "WAN IP: ";
 | 
			
		||||
            curl_easy_setopt(api_curl, CURLOPT_URL,
 | 
			
		||||
                    WIFI_PUBLIC_IP_URL);
 | 
			
		||||
 | 
			
		||||
            //peform request
 | 
			
		||||
            curl_easy_perform(api_curl);
 | 
			
		||||
 | 
			
		||||
            //parse the result
 | 
			
		||||
            public_ip += json_string;
 | 
			
		||||
        }
 | 
			
		||||
        //the public IP should have already been grabbed above
 | 
			
		||||
    }
 | 
			
		||||
    //this shows static info on the wifi network, which does need to change 
 | 
			
		||||
    //therefore, no update
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////
 | 
			
		||||
// Update the texture that is being
 | 
			
		||||
// Update the texture that is being 
 | 
			
		||||
// displayed. Due to the nature of what
 | 
			
		||||
// is being displayed, this will only
 | 
			
		||||
// ever be called once, as the wifi
 | 
			
		||||
@ -205,15 +110,24 @@ void wifi::update_texture(){
 | 
			
		||||
            board::getString(password_string.c_str(),
 | 
			
		||||
                { "Roboto_Mono/RobotoMono-Medium.ttf", 50 }), NULL, &tgt);
 | 
			
		||||
 | 
			
		||||
    tgt.y += tgt.h + 25;
 | 
			
		||||
    TTF_SizeText(board::getFont({ "Roboto_Mono/RobotoMono-Medium.ttf", 50 }),
 | 
			
		||||
            wan_status ? "Internet is up" : "Internet is down; reconnecting", &tgt.w, &tgt.h);
 | 
			
		||||
    SDL_RenderCopy(board::getRenderer(),
 | 
			
		||||
            board::getString(wan_status ? "Internet is up" : "Internet is down; reconnecting",
 | 
			
		||||
                { "Roboto_Mono/RobotoMono-Medium.ttf", 50 }), NULL, &tgt);
 | 
			
		||||
 | 
			
		||||
    //Get public ip address and display it
 | 
			
		||||
    if(WIFI_SHOW_PUBLIC_IP){
 | 
			
		||||
        std::string public_ip = "WAN IP: ";
 | 
			
		||||
        CURL* curl;
 | 
			
		||||
        curl = curl_easy_init();
 | 
			
		||||
 | 
			
		||||
        if(curl){
 | 
			
		||||
            CURLcode res;
 | 
			
		||||
            curl_easy_setopt(curl, CURLOPT_URL, WIFI_PUBLIC_IP_URL);
 | 
			
		||||
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, 
 | 
			
		||||
                    dashboard::panel::wifi::curl_callback);
 | 
			
		||||
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &public_ip);
 | 
			
		||||
            res = curl_easy_perform(curl);
 | 
			
		||||
            curl_easy_cleanup(curl);
 | 
			
		||||
        } else {
 | 
			
		||||
            public_ip += "Unkown";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        tgt.y += tgt.h + 25;
 | 
			
		||||
        TTF_SizeText(board::getFont({ "Roboto_Mono/RobotoMono-Medium.ttf", 50 }),
 | 
			
		||||
                public_ip.c_str(), &tgt.w, &tgt.h);
 | 
			
		||||
@ -222,29 +136,6 @@ void wifi::update_texture(){
 | 
			
		||||
                    { "Roboto_Mono/RobotoMono-Medium.ttf", 50 }), NULL, &tgt);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //TODO display speedtest info
 | 
			
		||||
    tgt.y += tgt.h + 25;
 | 
			
		||||
    TTF_SizeText(board::getFont({ "Roboto_Mono/RobotoMono-Medium.ttf", 50 }),
 | 
			
		||||
            speedtest_ping.c_str(), &tgt.w, &tgt.h);
 | 
			
		||||
    SDL_RenderCopy(board::getRenderer(),
 | 
			
		||||
            board::getString(speedtest_ping.c_str(),
 | 
			
		||||
                { "Roboto_Mono/RobotoMono-Medium.ttf", 50 }), NULL, &tgt);
 | 
			
		||||
 | 
			
		||||
    tgt.y += tgt.h + 25;
 | 
			
		||||
    TTF_SizeText(board::getFont({ "Roboto_Mono/RobotoMono-Medium.ttf", 50 }),
 | 
			
		||||
            speedtest_up.c_str(), &tgt.w, &tgt.h);
 | 
			
		||||
    SDL_RenderCopy(board::getRenderer(),
 | 
			
		||||
            board::getString(speedtest_up.c_str(),
 | 
			
		||||
                { "Roboto_Mono/RobotoMono-Medium.ttf", 50 }), NULL, &tgt);
 | 
			
		||||
 | 
			
		||||
    tgt.y += tgt.h + 25;
 | 
			
		||||
    TTF_SizeText(board::getFont({ "Roboto_Mono/RobotoMono-Medium.ttf", 50 }),
 | 
			
		||||
            speedtest_down.c_str(), &tgt.w, &tgt.h);
 | 
			
		||||
    SDL_RenderCopy(board::getRenderer(),
 | 
			
		||||
            board::getString(speedtest_down.c_str(),
 | 
			
		||||
                { "Roboto_Mono/RobotoMono-Medium.ttf", 50 }), NULL, &tgt);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    SDL_SetRenderTarget(board::getRenderer(), NULL);
 | 
			
		||||
}
 | 
			
		||||
@ -257,8 +148,8 @@ void wifi::initTexture(){
 | 
			
		||||
    std::cerr << "WIFI INIT TEXTURE\n";
 | 
			
		||||
    if(_texture == nullptr){
 | 
			
		||||
        _texture = SDL_CreateTexture(board::getRenderer(),
 | 
			
		||||
                SDL_PIXELFORMAT_RGBA8888,
 | 
			
		||||
                SDL_TEXTUREACCESS_TARGET,
 | 
			
		||||
                SDL_PIXELFORMAT_RGBA8888, 
 | 
			
		||||
                SDL_TEXTUREACCESS_TARGET, 
 | 
			
		||||
                SCREEN_WIDTH, SCREEN_HEIGHT);
 | 
			
		||||
 | 
			
		||||
        SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_BLEND);
 | 
			
		||||
@ -267,7 +158,7 @@ void wifi::initTexture(){
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////////
 | 
			
		||||
// Curl callback function
 | 
			
		||||
size_t dashboard::panel::wifi::curl_callback(void* contents, size_t size,
 | 
			
		||||
size_t dashboard::panel::wifi::curl_callback(void* contents, size_t size, 
 | 
			
		||||
        size_t nmemb, void* userp){
 | 
			
		||||
    ((std::string*)userp)->append((char*)contents, size * nmemb);
 | 
			
		||||
    return size * nmemb;
 | 
			
		||||
 | 
			
		||||
@ -13,10 +13,8 @@
 | 
			
		||||
#include <SDL2/SDL_ttf.h>
 | 
			
		||||
 | 
			
		||||
#include <curl/curl.h>
 | 
			
		||||
#include "../util/rapidjson/document.h"
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <chrono>
 | 
			
		||||
 | 
			
		||||
namespace dashboard::panel {
 | 
			
		||||
    class wifi : public panel {
 | 
			
		||||
@ -31,19 +29,6 @@ namespace dashboard::panel {
 | 
			
		||||
        void update();
 | 
			
		||||
        void update_texture();
 | 
			
		||||
        void initTexture();
 | 
			
		||||
 | 
			
		||||
        std::string public_ip;
 | 
			
		||||
        bool wan_status;
 | 
			
		||||
        std::string speedtest_up;
 | 
			
		||||
        std::string speedtest_down;
 | 
			
		||||
        std::string speedtest_ping;
 | 
			
		||||
 | 
			
		||||
        CURL* api_curl;
 | 
			
		||||
        std::string json_string;
 | 
			
		||||
        rapidjson::Document json_doc;
 | 
			
		||||
 | 
			
		||||
        std::chrono::time_point<std::chrono::high_resolution_clock> _last_update;
 | 
			
		||||
        std::chrono::milliseconds _update_interval;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,11 +16,11 @@ namespace dashboard::panel {
 | 
			
		||||
    constexpr size_t WIFI_DEFAULT_TIME_ON_SCREEN = 15000;
 | 
			
		||||
 | 
			
		||||
    //How long should we wait between updates? in ms
 | 
			
		||||
    //Default 60s
 | 
			
		||||
    //Due to the nature of this panel, this value is ignored
 | 
			
		||||
    constexpr size_t WIFI_UPDATE_INTERVAL = 60000;
 | 
			
		||||
 | 
			
		||||
    //Set to true to have your public IP be shown on the wifi page
 | 
			
		||||
    //Will make a curl request to WIFI_PUBLIC_IP_URL when the frame
 | 
			
		||||
    //Will make a curl request to WIFI_PUBLIC_IP_URL when the frame 
 | 
			
		||||
    //is rendered. This this is a privacy concern disable this option
 | 
			
		||||
    constexpr bool WIFI_SHOW_PUBLIC_IP = true;
 | 
			
		||||
    constexpr char WIFI_PUBLIC_IP_URL[] = "http://ipinfo.io/ip";
 | 
			
		||||
@ -31,36 +31,4 @@ namespace dashboard::panel {
 | 
			
		||||
    constexpr char WIFI_NETWORK_NAME[] = "MyNetwork";
 | 
			
		||||
    constexpr char WIFI_NETWORK_PASS[] = "MyPassword";
 | 
			
		||||
 | 
			
		||||
    // Set to true if you have home assistant on your network
 | 
			
		||||
    // If you do, you can do alot more with it, including showing number of
 | 
			
		||||
    // clients, network speed, etc
 | 
			
		||||
    constexpr bool WIFI_HOMEASSISTANT = true;
 | 
			
		||||
 | 
			
		||||
    //API and URL for home assistant. If using the home assistant panel, this
 | 
			
		||||
    //should be the same
 | 
			
		||||
    constexpr char WIFI_HOMEASSISTANT_APIKEY[] = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxYTNhNDhhYTBlZDM0MjkyOTk5OWZhNGVjZGRjMGUwMCIsImlhdCI6MTY0MjE4NDU0MCwiZXhwIjoxOTU3NTQ0NTQwfQ.Zdy7-ZwX0HuwhmUGeLhF5XCluotsKmpDqmi5o-hQZCc";
 | 
			
		||||
    constexpr char WIFI_HOMEASSISTANT_URL[] = "http://192.168.1.104:8123/api/states";
 | 
			
		||||
 | 
			
		||||
    //Name of the external IP sensor entry in home assistant
 | 
			
		||||
    //If your router integrates with it, then you should be able to find it in
 | 
			
		||||
    //integrations
 | 
			
		||||
    constexpr char WIFI_HOMEASSISTANT_ROUTER_EXTERNAL_IP[] = "sensor.r7000p_gateway_external_ip";
 | 
			
		||||
 | 
			
		||||
    //Name of WAN status sensor in home assistant
 | 
			
		||||
    constexpr char WIFI_HOMEASSISTANT_ROUTER_WAN_STATUS[] = "sensor.r7000p_gateway_wan_status";
 | 
			
		||||
 | 
			
		||||
    //Enable this if you have the ookla speedtest module on home assistant
 | 
			
		||||
    constexpr bool WIFI_HOMEASSISTANT_SPEEDTEST = true;
 | 
			
		||||
 | 
			
		||||
    //Name of the entity id string used by the speedtest upload sensor in home
 | 
			
		||||
    //assistant
 | 
			
		||||
    constexpr char WIFI_HOMEASSISTANT_SPEEDTEST_UP[] = "sensor.speedtest_upload";
 | 
			
		||||
 | 
			
		||||
    //Name of the entity id string used by the speedtest download sensor in home
 | 
			
		||||
    //assistant
 | 
			
		||||
    constexpr char WIFI_HOMEASSISTANT_SPEEDTEST_DOWN[] = "sensor.speedtest_download";
 | 
			
		||||
 | 
			
		||||
    //Name of the entity id string used by the speedtest ping sensor in home
 | 
			
		||||
    //assistant
 | 
			
		||||
    constexpr char WIFI_HOMEASSISTANT_SPEEDTEST_PING[] = "sensor.speedtest_ping";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,10 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
API_KEY=$(pass gluttony/homeassistant/API)
 | 
			
		||||
IP_ADDR="192.168.1.104"
 | 
			
		||||
 | 
			
		||||
curl -X GET \
 | 
			
		||||
    -H "Authorization: Bearer $API_KEY" \
 | 
			
		||||
    -H "Content-Type: application/json" \
 | 
			
		||||
    -o out.json \
 | 
			
		||||
    http://$IP_ADDR:8123/api/states
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user