DS1307_Command.cpp
5.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
DS1307_Command.cpp - CLI library for Arduino/ESP8266 - DS1307 Command implementation
Version 1.0, latest version, documentation and bugtracker available at:
https://gitlab.lindenaar.net/arduino/CLI
Copyright (c) 2019 Frederik Lindenaar
This library is free software: you can redistribute it and/or modify it under
the terms of version 3 of the GNU General Public License as published by the
Free Software Foundation, or (at your option) a later version of the license.
This code is distributed in the hope that it will be useful but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, visit <http://www.gnu.org/licenses/> to download it.
*/
#include <TimeLib.h>
#include <DS1307RTC.h>
#include "DS1307_Command.h"
DS1307_Command::DS1307_Command(CLI &cli) : // Constructor for ds1307 command
CLI_Command(cli, // CLI to register with
PSTR("ds1307"), // Command name
PSTR("Set and/or show DS1307 RTC date and time"), // Description
PSTR("Usage:\tds1307 [YYYY-MM-DD] [HH:MM[:SS]]\n" // Usage Help
"where YYYY-MM-DD is the date in ISO format\n"
" and HH:MM[:SS] the new time (seconds are optional)\n")) { };
// macro to determine whether the given year is a leap year
#define LEAP_YEAR(y) (!((y) % 4) && (((y) % 100 ) || !((y) % 400) ))
inline uint8_t monthDays(int y, uint8_t m) { // get number of days for month
return (m == 2) ? 28 + LEAP_YEAR(y) : 30 + ((m & 1) == (m <= 7));
}
// Function below parses the string passed in params (if provided) and sets the
// time accordingly. returns false in case an invalid date/time was found (and
// an invalid parameter message will be given) and true in case of no params or
// when a string of the format: [YYYY-MM-DD] [HH:MM[:SS]] is found. In case a
// partial date/time is provided, the remaining part will be substituted with
// the DS1307's current value. Additional whitespaces are ignored and values are
// checked for validity.
bool DS1307_Command::setparams(const char *params) {
if (!params) return true; // return true when no parameter
int value;
tmElements_t tm;
if (const char *sep = CLI_STR_parseInt(params, value)) { // parse first integer value
RTC.read(tm); // Got a valid start get current time
// check if character following the integer is a '-' and we have a valid year
if (*sep == '-' && value >= tmYearToCalendar(0) && value <= tmYearToCalendar(255)) {
// Got a valid year and date separator, parse the rest of the date
tm.Year = CalendarYrToTm(value);
if ((sep = CLI_STR_parseInt(sep + 1, value)) && value >= 1 && value <= 12 && *sep == '-') {
tm.Month = value;
if ((sep = CLI_STR_parseInt(sep + 1, value)) && value >= 1 &&
value <= monthDays(tmYearToCalendar(tm.Year), value)) {
tm.Day = value;
sep = CLI_STR_skipSep(sep);
if (*sep) sep = CLI_STR_parseInt(sep, value); // parse the hour integer
} else return false; // exit if parsing a date and day is invald
} else return false; // exit if parsing a date and month is invald
}
// check if character following the integer is a ':' and we have a valid hour
if (*sep == ':' && value >= 0 && value < 24) {
// Got a valid hour and time separator, parse the rest of the time
tm.Hour = value;
if ((sep = CLI_STR_parseInt(sep + 1, value)) && value >= 0 && value <= 59) {
tm.Minute = value;
if (*sep == ':') { // if next char is a separator, parse seconds
if ((sep = CLI_STR_parseInt(sep + 1, value)) && value >= 0 && value <= 59) {
tm.Second = value;
} else return false;
} else tm.Second = 0; // otherwise set seconds to 0
} else return false; // exit if minutes is invalid
}
if (*CLI_STR_skipSep(sep)) return false; // if not the end of the string, return false
RTC.write(tm); // if we get here, we have a valid time in tm, set it
return true; // return true as we got valid input
}
return false; // no valid parameter, return false
}
bool DS1307_Command::execute(CLI &cli) { // execute prints the current time
tmElements_t tm;
if (RTC.read(tm)) { // get current time from DS1307
cli.print(dayStr(tm.Wday)); // print day of week
cli.print(' ');
cli.print(tm.Day); // print day of month
cli.print(' ');
cli.print(monthStr(tm.Month)); // print month name
cli.print(' ');
cli.print(tmYearToCalendar(tm.Year)); // print year
cli.print(' ');
cli.print2digits(tm.Hour); // print hour
cli.print(':');
cli.print2digits(tm.Minute); // print minute
cli.print(':');
cli.print2digits(tm.Second); // print seconds
} else { // if get time fails, print an error
if (RTC.chipPresent()) { // if a chip was found, it is not set
cli.print_P(PSTR("Error: cannot read RTC clock, please set time\n"));
} else { // otherwise tell user no DS1307 was found
cli.print_P(PSTR("Error: RTC clock not found, check wiring\n"));
}
}
return false; // We're done and should not be called again
}