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 && OPENTHREAD_FTD
40 #error "OPENTHREAD_CONFIG_UPTIME_ENABLE is required for FTD"
41 #endif
42 
43 #if OPENTHREAD_CONFIG_UPTIME_ENABLE
44 
45 #include "common/locator.hpp"
46 #include "common/non_copyable.hpp"
47 #include "common/string.hpp"
48 #include "common/time.hpp"
49 #include "common/timer.hpp"
50 
51 namespace ot {
52 
53 /**
54  * Implements tracking of device uptime (in msec).
55  *
56  */
57 class Uptime : public InstanceLocator, private NonCopyable
58 {
59 public:
60     static constexpr uint16_t kStringSize = OT_UPTIME_STRING_SIZE; ///< Recommended string size to represent uptime.
61 
62     /**
63      * Initializes an `Uptime` instance.
64      *
65      * @param[in] aInstance   The OpenThread instance.
66      *
67      */
68     explicit Uptime(Instance &aInstance);
69 
70     /**
71      * Returns the current device uptime (in msec).
72      *
73      * The uptime is maintained as number of milliseconds since OpenThread instance was initialized.
74      *
75      * @returns The uptime (number of milliseconds).
76      *
77      */
78     uint64_t GetUptime(void) const;
79 
80     /**
81      * Gets the current uptime as a human-readable string.
82      *
83      * The string follows the format "<hh>:<mm>:<ss>.<mmmm>" for hours, minutes, seconds and millisecond (if uptime is
84      * shorter than one day) or "<dd>d.<hh>:<mm>:<ss>.<mmmm>" (if longer than a day).
85      *
86      * If the resulting string does not fit in @p aBuffer (within its @p aSize characters), the string will be
87      * truncated but the outputted string is always null-terminated.
88      *
89      * @param[out] aBuffer   A pointer to a char array to output the string.
90      * @param[in]  aSize     The size of @p aBuffer (in bytes). Recommended to use `OT_UPTIME_STRING_SIZE`.
91      *
92      */
93     void GetUptime(char *aBuffer, uint16_t aSize) const;
94 
95     /**
96      * Converts an uptime value (number of milliseconds) to a human-readable string.
97      *
98      * The string follows the format "<hh>:<mm>:<ss>.<mmmm>" for hours, minutes, seconds and millisecond (if uptime is
99      * shorter than one day) or "<dd>d.<hh>:<mm>:<ss>.<mmmm>" (if longer than a day). @p aIncludeMsec can be used
100      * to determine whether `.<mmm>` milliseconds is included or omitted in the resulting string.
101      *
102      * @param[in]     aUptime        The uptime to convert.
103      * @param[in,out] aWriter        A `StringWriter` to append the converted string to.
104      * @param[in]     aIncludeMsec   Whether to include `.<mmm>` milliseconds in the string.
105      *
106      */
107     static void UptimeToString(uint64_t aUptime, StringWriter &aWriter, bool aIncludeMsec);
108 
109     /**
110      * Converts a given uptime as number of milliseconds to number of seconds.
111      *
112      * @param[in] aUptimeInMilliseconds    Uptime in milliseconds (as `uint64_t`).
113      *
114      * @returns The converted @p aUptimeInMilliseconds to seconds (as `uint32_t`).
115      *
116      */
MsecToSec(uint64_t aUptimeInMilliseconds)117     static uint32_t MsecToSec(uint64_t aUptimeInMilliseconds)
118     {
119         return static_cast<uint32_t>(aUptimeInMilliseconds / 1000u);
120     }
121 
122     /**
123      * Converts a given uptime as number of seconds to number of milliseconds.
124      *
125      * @param[in] aUptimeInSeconds    Uptime in seconds (as `uint32_t`).
126      *
127      * @returns The converted @p aUptimeInSeconds to milliseconds (as `uint64_t`).
128      *
129      */
SecToMsec(uint32_t aUptimeInSeconds)130     static uint64_t SecToMsec(uint32_t aUptimeInSeconds) { return static_cast<uint64_t>(aUptimeInSeconds) * 1000u; }
131 
132 private:
133     static constexpr uint32_t kTimerInterval = (1 << 30);
134 
135     static_assert(static_cast<uint32_t>(4 * kTimerInterval) == 0, "kTimerInterval is not correct");
136 
137     void HandleTimer(void);
138 
139     using UptimeTimer = TimerMilliIn<Uptime, &Uptime::HandleTimer>;
140 
141     TimeMilli   mStartTime;
142     uint32_t    mOverflowCount;
143     UptimeTimer mTimer;
144 };
145 
146 } // namespace ot
147 
148 #endif // OPENTHREAD_CONFIG_UPTIME_ENABLE
149 
150 #endif // UPTIME_HPP_
151