1 /*
2  *  Copyright (c) 2021, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file includes definitions for tracking device's uptime.
32  */
33 
34 #ifndef UPTIME_HPP_
35 #define UPTIME_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
40 
41 #include "common/locator.hpp"
42 #include "common/non_copyable.hpp"
43 #include "common/string.hpp"
44 #include "common/time.hpp"
45 #include "common/timer.hpp"
46 
47 namespace ot {
48 
49 /**
50  * This class implements tracking of device uptime (in msec).
51  *
52  */
53 class Uptime : public InstanceLocator, private NonCopyable
54 {
55 public:
56     /**
57      * This constructor initializes an `Uptime` instance.
58      *
59      * @param[in] aInstance   The OpenThread instance.
60      *
61      */
62     explicit Uptime(Instance &aInstance);
63 
64     /**
65      * This method returns the current device uptime (in msec).
66      *
67      * The uptime is maintained as number of milliseconds since OpenThread instance was initialized.
68      *
69      * @returns The uptime (number of milliseconds).
70      *
71      */
72     uint64_t GetUptime(void) const;
73 
74     /**
75      * This method gets the current uptime as a human-readable string.
76      *
77      * The string follows the format "<hh>:<mm>:<ss>.<mmmm>" for hours, minutes, seconds and millisecond (if uptime is
78      * shorter than one day) or "<dd>d.<hh>:<mm>:<ss>.<mmmm>" (if longer than a day).
79      *
80      * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
81      * truncated but the outputted string is always null-terminated.
82      *
83      * @param[out] aBuffer   A pointer to a char array to output the string.
84      * @param[in]  aSize     The size of @p aBuffer (in bytes). Recommended to use `OT_UPTIME_STRING_SIZE`.
85      *
86      */
87     void GetUptime(char *aBuffer, uint16_t aSize) const;
88 
89     /**
90      * This method converts an uptime value (number of milliseconds) to a human-readable string.
91      *
92      * The string follows the format "<hh>:<mm>:<ss>.<mmmm>" for hours, minutes, seconds and millisecond (if uptime is
93      * shorter than one day) or "<dd>d.<hh>:<mm>:<ss>.<mmmm>" (if longer than a day). @p aIncludeMsec can be used
94      * to determine whether `.<mmm>` milliseconds is included or omitted in the resulting string.
95      *
96      * @param[in]     aUptime        The uptime to convert.
97      * @param[in,out] aWriter        A `StringWriter` to append the converted string to.
98      * @param[in]     aIncludeMsec   Whether to include `.<mmm>` milliseconds in the string.
99      *
100      */
101     static void UptimeToString(uint64_t aUptime, StringWriter &aWriter, bool aIncludeMsec);
102 
103     /**
104      * This static method converts a given uptime as number of milliseconds to number of seconds.
105      *
106      * @param[in] aUptimeInMilliseconds    Uptime in milliseconds (as `uint64_t`).
107      *
108      * @returns The converted @p aUptimeInMilliseconds to seconds (as `uint32_t`).
109      *
110      */
MsecToSec(uint64_t aUptimeInMilliseconds)111     static uint32_t MsecToSec(uint64_t aUptimeInMilliseconds)
112     {
113         return static_cast<uint32_t>(aUptimeInMilliseconds / 1000u);
114     }
115 
116     /**
117      * This static method converts a given uptime as number of seconds to number of milliseconds.
118      *
119      * @param[in] aUptimeInSeconds    Uptime in seconds (as `uint32_t`).
120      *
121      * @returns The converted @p aUptimeInSeconds to milliseconds (as `uint64_t`).
122      *
123      */
SecToMsec(uint32_t aUptimeInSeconds)124     static uint64_t SecToMsec(uint32_t aUptimeInSeconds) { return static_cast<uint64_t>(aUptimeInSeconds) * 1000u; }
125 
126 private:
127     static constexpr uint32_t kTimerInterval = (1 << 30);
128 
129     static_assert(static_cast<uint32_t>(4 * kTimerInterval) == 0, "kTimerInterval is not correct");
130 
131     void HandleTimer(void);
132 
133     using UptimeTimer = TimerMilliIn<Uptime, &Uptime::HandleTimer>;
134 
135     TimeMilli   mStartTime;
136     uint32_t    mOverflowCount;
137     UptimeTimer mTimer;
138 };
139 
140 } // namespace ot
141 
142 #endif // OPENTHREAD_CONFIG_UPTIME_ENABLE
143 
144 #endif // UPTIME_HPP_
145