d_clock.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
  2. // Example of a clock. This is very similar to the text-example,
  3. // except that it shows the time :)
  4. //
  5. // This code is public domain
  6. // (but note, that the led-matrix library this depends on is GPL v2)
  7. #include "led-matrix.h"
  8. #include "graphics.h"
  9. #include <getopt.h>
  10. #include <signal.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <time.h>
  15. #include <unistd.h>
  16. #include <vector>
  17. #include <string>
  18. // demure added
  19. #include <ctime>
  20. #include <iostream>
  21. #include "json.hpp" //<nlohmann/json.hpp>
  22. using json = nlohmann::json;
  23. using namespace rgb_matrix;
  24. volatile bool interrupt_received = false;
  25. static void InterruptHandler(int signo) {
  26. interrupt_received = true;
  27. }
  28. static int usage(const char *progname) {
  29. fprintf(stderr, "usage: %s [options]\n", progname);
  30. fprintf(stderr, "Reads text from stdin and displays it. "
  31. "Empty string: clear screen\n");
  32. fprintf(stderr, "Options:\n");
  33. fprintf(stderr,
  34. //"\t-f <font-file> : Use given font.\n"
  35. //"\t-C <r,g,b> : Color. Default 255,255,0\n"
  36. //"\t-B <r,g,b> : Background-Color. Default 0,0,0\n"
  37. "\tTest : Description\n"
  38. "\n"
  39. );
  40. rgb_matrix::PrintMatrixFlags(stderr);
  41. return 1;
  42. }
  43. //static bool parseColor( Color *c, const char *str) {
  44. //return sscanf(str, "%hhu,%hhu,%hhu", &c->r, &c->g, &c->b) == 3;
  45. //}
  46. // Initialize rgb_matrix color structs
  47. // Values here don't matter...
  48. Color ct_time(0, 0, 200);
  49. Color ct_week(0, 125, 125);
  50. Color ct_date(125, 0, 125);
  51. Color ct_utc(150, 0, 0);
  52. Color ct_epoch(0, 150, 0);
  53. Color ct_temp(125, 125, 125);
  54. Color ct_humid(125, 125, 0);
  55. Color ct_sun(150, 75, 0);
  56. Color ct_rand(150, 150, 150); //DEBUG
  57. int main(int argc, char *argv[]) {
  58. RGBMatrix::Options matrix_options;
  59. rgb_matrix::RuntimeOptions runtime_opt;
  60. if (!rgb_matrix::ParseOptionsFromFlags(&argc, &argv,
  61. &matrix_options, &runtime_opt)) {
  62. return usage(argv[0]);
  63. }
  64. // Set Default LED Matrix Conf
  65. matrix_options.rows = 64;
  66. matrix_options.cols = 64;
  67. matrix_options.hardware_mapping = "adafruit-hat";
  68. //int opt;
  69. //while ((opt = getopt(argc, argv, "f:C:")) != -1) {
  70. //switch (opt) {
  71. //case 'f': bdf_font_file = strdup(optarg); break;
  72. //case 'C':
  73. //if (!parseColor(&color, optarg)) {
  74. //fprintf(stderr, "Invalid color spec: %s\n", optarg);
  75. //return usage(argv[0]);
  76. //}
  77. //break;
  78. //default:
  79. //return usage(argv[0]);
  80. //}
  81. //}
  82. /// Font Loading /// {{{
  83. const char *ft_16x32_file = "/led_matrix/spleen/spleen-16x32.bdf";
  84. rgb_matrix::Font ft_16x32;
  85. if (!ft_16x32.LoadFont(ft_16x32_file)) {
  86. fprintf(stderr, "Couldn't load font '%s'\n", ft_16x32_file);
  87. return 1;
  88. }
  89. const char *ft_12x24_file = "/led_matrix/spleen/spleen-12x24.bdf";
  90. rgb_matrix::Font ft_12x24;
  91. if (!ft_12x24.LoadFont(ft_12x24_file)) {
  92. fprintf(stderr, "Couldn't load font '%s'\n", ft_12x24_file);
  93. return 1;
  94. }
  95. const char *ft_8x16_file = "/led_matrix/spleen/spleen-8x16.bdf";
  96. rgb_matrix::Font ft_8x16;
  97. if (!ft_8x16.LoadFont(ft_8x16_file)) {
  98. fprintf(stderr, "Couldn't load font '%s'\n", ft_8x16_file);
  99. return 1;
  100. }
  101. const char *ft_5x8_file = "/led_matrix/spleen/spleen-5x8.bdf";
  102. rgb_matrix::Font ft_5x8;
  103. if (!ft_5x8.LoadFont(ft_5x8_file)) {
  104. fprintf(stderr, "Couldn't load font '%s'\n", ft_5x8_file);
  105. return 1;
  106. }
  107. /// End Font Loading /// }}}
  108. RGBMatrix *matrix = RGBMatrix::CreateFromOptions(matrix_options, runtime_opt);
  109. if (matrix == NULL)
  110. return 1;
  111. FrameCanvas *offscreen = matrix->CreateFrameCanvas();
  112. struct timespec next_time;
  113. next_time.tv_sec = time(NULL);
  114. next_time.tv_nsec = 0;
  115. struct tm tm;
  116. signal(SIGTERM, InterruptHandler);
  117. signal(SIGINT, InterruptHandler);
  118. // Set Background Color
  119. Color bg_color(0, 0, 0);
  120. while (!interrupt_received) {
  121. // Clear screen by overwriting with background color
  122. offscreen->Fill(bg_color.r, bg_color.g, bg_color.b);
  123. localtime_r(&next_time.tv_sec, &tm);
  124. /// Set Time Vars /// {{{
  125. // Normal Time
  126. time_t rawtime;
  127. struct tm * timeinfo;
  128. time (&rawtime);
  129. timeinfo = localtime (&rawtime);
  130. // Declare Normal Time Vars
  131. char t_time [8];
  132. char t_time_late [8];
  133. char t_week [10];
  134. char t_week_late [8];
  135. char t_date [16];
  136. char t_epoch [16];
  137. char t_hour [8];
  138. // Format Normal Time
  139. strftime (t_time,8,"%R",timeinfo);
  140. strftime (t_time_late,8,"%H%M",timeinfo);
  141. strftime (t_week,10,"%a, %b",timeinfo);
  142. strftime (t_week_late,8,"%a",timeinfo);
  143. strftime (t_date,16,"%F",timeinfo);
  144. strftime (t_epoch,16,"%s",timeinfo);
  145. strftime (t_hour,8,"%H",timeinfo);
  146. // Normal Time Vars for Tests
  147. int now_h = atoi(t_hour);
  148. int now_s = atoi(t_epoch);
  149. // UTC Time
  150. time_t utc_time;
  151. struct tm * tm_gmt;
  152. utc_time = time(NULL);
  153. tm_gmt = gmtime(&utc_time);
  154. char t_utc [10];
  155. strftime (t_utc,10,"%R UTC",tm_gmt);
  156. /// End Set Time Vars /// }}}
  157. /// Weather ///
  158. // Weather Lookup
  159. auto weather = json::parse(R"({"coord": {"lon": -10.000, "lat": 10.0000}, "weather": [{"id": 800, "main": "Clear", "description": "clear sky", "icon": "01n"}], "base": "stations", "main": {"temp": 292.48, "feels_like": 292.22, "temp_min": 290.19, "temp_max": 295.2, "pressure": 1016, "humidity": 67}, "visibility": 10000, "wind": {"speed": 2.06, "deg": 340}, "clouds": {"all": 1}, "dt": 1625274979, "sys": {"type": 2, "id": 1000000, "country": "US", "sunrise": 1625220143, "sunset": 1625275865}, "timezone": -14400, "id": 0000000, "name": "CITY", "cod": 200})"); //DEBUG
  160. // Weather Vars
  161. // Weather Pull Status
  162. int wi_cod = weather["cod"].get<int>();
  163. // Get K temp, Math K to F, and store as char
  164. char wc_temp_f [8];
  165. std::sprintf(wc_temp_f, "%dF", (int)round((weather["main"]["temp"].get<int>() - 273.15) * 9/5 + 32));
  166. // Humidity
  167. char wc_humid [8];
  168. std::sprintf(wc_humid, "%d%%H", weather["main"]["humidity"].get<int>());
  169. // Sunrise
  170. // TODO: strftime and store char array %H%M version for LED display
  171. int wi_sunrise = weather["sys"]["sunrise"].get<int>();
  172. int wi_sunset = weather["sys"]["sunset"].get<int>();
  173. // Convert Weather Sun Times
  174. time_t tm_sunrise = wi_sunrise;
  175. char wc_sunrise [8];
  176. strftime (wc_sunrise,8,"%H%M*",localtime(&tm_sunrise));
  177. time_t tm_sunset = wi_sunset;
  178. char wc_sunset [8];
  179. strftime (wc_sunset,8,"%H%M*",localtime(&tm_sunset));
  180. // Store Last Weather Update Time
  181. int wi_up = weather["dt"].get<int>();
  182. /// End Weather ///
  183. /// Test for Night Mode /// {{{
  184. bool night_mode; // declare var
  185. if (wi_sunset != 0 and (now_s - wi_up) < 21600) {
  186. if (now_s > wi_sunset or now_s < wi_sunrise) {
  187. night_mode = true;
  188. }
  189. else {
  190. night_mode = false;
  191. }
  192. }
  193. else {
  194. if (now_h < 7 or now_h > 21) {
  195. night_mode = true;
  196. }
  197. else {
  198. night_mode = false;
  199. }
  200. }
  201. /// End Test for Night Mode /// }}}
  202. /// Set Output Colors /// {{{
  203. // Test for night mode
  204. //if (now_h < 7 or now_h > 21) {
  205. if (night_mode == true) {
  206. ct_time.r = 30; ct_time.g = 0; ct_time.b = 0;
  207. ct_week.r = 30; ct_week.g = 0; ct_week.b = 0;
  208. ct_date.r = 30; ct_date.g = 0; ct_date.b = 0;
  209. ct_utc.r = 30; ct_utc.g = 0; ct_utc.b = 0;
  210. ct_epoch.r = 30; ct_epoch.g = 0; ct_epoch.b = 0;
  211. ct_temp.r = 30; ct_temp.g = 0; ct_temp.b = 0;
  212. ct_humid.r = 30; ct_humid.g = 0; ct_humid.b = 0;
  213. ct_sun.r = 30; ct_sun.g = 0; ct_sun.b = 0;
  214. ct_rand.r = 30; ct_rand.g = 0; ct_rand.b = 0; //DEBUG
  215. }
  216. // Else Day mode
  217. else {
  218. ct_time.r = 0; ct_time.g = 0; ct_time.b = 200;
  219. ct_week.r = 0; ct_week.g = 125; ct_week.b = 125;
  220. ct_date.r = 125; ct_date.g = 0; ct_date.b = 125;
  221. ct_utc.r = 150; ct_utc.g = 0; ct_utc.b = 0;
  222. ct_epoch.r = 0; ct_epoch.g = 150; ct_epoch.b = 0;
  223. ct_temp.r = 125; ct_temp.g = 125; ct_temp.b = 125;
  224. ct_humid.r = 125; ct_humid.g = 125; ct_humid.b = 0;
  225. ct_sun.r = 150; ct_sun.g = 75; ct_sun.b = 0;
  226. //ct_rand.r = 30; ct_rand.g = 0; ct_rand.b = 0; //DEBUG
  227. ct_rand.r = rand() % 100; ct_rand.g = rand() % 100; ct_rand.b = rand() % 100; //DEBUG
  228. }
  229. ///End Set Output Colors /// }}}
  230. /// Display LED output ///
  231. if (now_h <= 6) {
  232. // Location, font, X, Y, Color, BG_Color, String, Char_Spacing;
  233. rgb_matrix::DrawText(offscreen, ft_16x32, 0, 20, ct_time, NULL, t_time_late, 0);
  234. rgb_matrix::DrawText(offscreen, ft_16x32, 0, 42, ct_week, NULL, t_week_late, 0);
  235. // Display Night Temp
  236. rgb_matrix::DrawText(offscreen, ft_16x32, 0, 64, ct_temp, NULL, wc_temp_f, 0);
  237. } else {
  238. // Location, font, X, Y, Color, BG_Color, String, Char_Spacing;
  239. rgb_matrix::DrawText(offscreen, ft_12x24, 2, 15, ct_time, NULL, t_time, 0);
  240. rgb_matrix::DrawText(offscreen, ft_5x8, 0, 43, ct_week, NULL, t_week, 0);
  241. rgb_matrix::DrawText(offscreen, ft_5x8, 0, 50, ct_date, NULL, t_date, 0);
  242. rgb_matrix::DrawText(offscreen, ft_5x8, 0, 57, ct_utc, NULL, t_utc, 0);
  243. rgb_matrix::DrawText(offscreen, ft_5x8, 0, 64, ct_epoch, NULL, t_epoch, 0);
  244. // Display Day Weather
  245. rgb_matrix::DrawText(offscreen, ft_8x16, 0, 27, ct_temp, NULL, wc_temp_f, 0);
  246. rgb_matrix::DrawText(offscreen, ft_5x8, 0, 35, ct_humid, NULL, wc_humid, 0);
  247. //rgb_matrix::DrawText(offscreen, ft_5x8, 25, 35, ct_sun, NULL, "XXXX*", 0);
  248. if (now_s < wi_sunrise) {
  249. //printf("Sunrise is next at %s.\n",wc_sunrise);
  250. //printf("Sunrise is next at %d.\n",wi_sunrise);
  251. rgb_matrix::DrawText(offscreen, ft_5x8, 25, 35, ct_sun, NULL, wc_sunrise, 0);
  252. }
  253. else if (now_s < wi_sunset) {
  254. //printf("Sunset is next at %s.\n",wc_sunset);
  255. //printf("Sunset is next at %d.\n",wi_sunset);
  256. rgb_matrix::DrawText(offscreen, ft_5x8, 25, 35, ct_sun, NULL, wc_sunset, 0);
  257. }
  258. }
  259. rgb_matrix::DrawText(offscreen, ft_5x8, 59, 64, ct_rand, NULL, "+", 0); //DEBUG
  260. /// End Display LED output ///
  261. // Wait until we're ready to show it.
  262. clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &next_time, NULL);
  263. // Atomic swap with double buffer
  264. offscreen = matrix->SwapOnVSync(offscreen);
  265. next_time.tv_sec += 1;
  266. }
  267. // Finished. Shut down the RGB matrix.
  268. delete matrix;
  269. write(STDOUT_FILENO, "\n", 1); // Create a fresh new line after ^C on screen
  270. return 0;
  271. }