Skip to content

Commit fd1481a

Browse files
Add Energy Calendar usage
1 parent f36eb4c commit fd1481a

File tree

4 files changed

+485
-8
lines changed

4 files changed

+485
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,399 @@
1+
/*
2+
* Copyright (c) 2024 Project CHIP Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <app/AttributeAccessInterface.h>
18+
#include <app/AttributeAccessInterfaceRegistry.h>
19+
#include <app/ConcreteAttributePath.h>
20+
#include <app/InteractionModelEngine.h>
21+
#include <app/util/attribute-storage.h>
22+
23+
#include "energy-calendar-instance.h"
24+
25+
using namespace chip;
26+
using namespace chip::app;
27+
using namespace chip::app::DataModel;
28+
using namespace chip::app::Clusters;
29+
using namespace chip::app::Clusters::EnergyCalendar;
30+
using namespace chip::app::Clusters::EnergyCalendar::Attributes;
31+
using chip::Protocols::InteractionModel::Status;
32+
33+
namespace chip {
34+
namespace app {
35+
namespace Clusters {
36+
namespace EnergyCalendar {
37+
38+
constexpr uint32_t kOneDay = 24 * 60 * 60;
39+
40+
static TransitionDayOfWeekBitmap GetWeekDate(uint32_t date)
41+
{
42+
tm calendarTime{};
43+
time_t dt = date;
44+
localtime_r(&dt, &calendarTime);
45+
return (TransitionDayOfWeekBitmap)(calendarTime.tm_wday);
46+
}
47+
48+
void CalendarProviderInstance::Init(void)
49+
{
50+
}
51+
52+
static uint32_t GetCurrentDateTime(void)
53+
{
54+
System::Clock::Timestamp time = System::SystemClock().GetMonotonicTimestamp();
55+
using cast = std::chrono::duration<std::uint64_t>;
56+
uint64_t msec = std::chrono::duration_cast< cast >(time).count();
57+
58+
return static_cast<uint32_t>(msec / 1000);
59+
}
60+
61+
void CalendarProviderInstance::SetDefault(void)
62+
{
63+
uint32_t date = GetCurrentDateTime();
64+
uint32_t time = date % kOneDay;
65+
date -= time;
66+
67+
Structs::DayStruct::Type day = { .date = {},
68+
.transitions = {
69+
{ .transitionTime = 0, .PriceTier = 10},
70+
{ .transitionTime = 1000, .PriceTier = 20}
71+
},
72+
.calendarID = chip::Optional<uint32_t>(123) };
73+
74+
Structs::PeakPeriodStruct::Type peak = { .severity = PeakPeriodSeverityEnum::kHigh, .peakPeriod = 100, .startTime = 2000, .endTime = 2200 };
75+
76+
DataModel::DecodableList<Structs::CalendarPeriodStruct::Type> calendarPeriods = {};
77+
DataModel::DecodableList<Structs::DayStruct::Type> specialDays = {};
78+
79+
SetCommonAttributes(1, "Test", 123, 1);
80+
SetCalendarPeriod(date, calendarPeriods);
81+
SetSpecialDays(specialDays);
82+
SetCurrentAndNextDays(DataModel::MakeNullable(day), DataModel::MakeNullable(day));
83+
SetPeakPeriods(DataModel::MakeNullable(peak), DataModel::MakeNullable(peak));
84+
}
85+
86+
CHIP_ERROR CalendarProviderInstance::LoadJson(Json::Value & root)
87+
{
88+
DataModel::Nullable<uint32_t> calendarID;
89+
DataModel::Nullable<std::string> name;
90+
DataModel::Nullable<uint32_t> providerID;
91+
DataModel::Nullable<uint32_t> eventID;
92+
DataModel::Nullable<uint32_t> startDate;
93+
DataModel::DecodableList<Structs::DayStruct::Type> specialDays;
94+
DataModel::DecodableList<Structs::DayStruct::Type> currentDay;
95+
DataModel::DecodableList<Structs::DayStruct::Type> nextDay;
96+
DataModel::DecodableList<Structs::PeakPeriodStruct::Type> currentPeak;
97+
DataModel::DecodableList<Structs::PeakPeriodStruct::Type> nextPeak;
98+
99+
auto value = root.get("CalendarID", Json::Value());
100+
if (!value.empty())
101+
{
102+
calendarID.SetNonNull(value.asInt());
103+
}
104+
105+
auto value = root.get("Name", Json::Value());
106+
if (!value.empty())
107+
{
108+
name.SetNonNull(value.asString());
109+
}
110+
111+
auto value = root.get("ProviderID", Json::Value());
112+
if (!value.empty())
113+
{
114+
providerID.SetNonNull(value.asInt());
115+
}
116+
117+
auto value = root.get("EventID", Json::Value());
118+
if (!value.empty())
119+
{
120+
eventID.SetNonNull(value.asInt());
121+
}
122+
123+
SetCommonAttributes(calendarID, name, providerID, eventID);
124+
125+
auto value = root.get("StartDate", Json::Value());
126+
if (!value.empty())
127+
{
128+
startDate.SetNonNull(value.asInt());
129+
}
130+
131+
if (root.hasValue("CalendarPeriods"))
132+
{
133+
Json::FastWriter writer;
134+
const std::string json = writer.write(root["CalendarPeriods"]);
135+
136+
TLV::TLVReader reader;
137+
reader.Init(json);
138+
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::AnonymousTag()));
139+
ReturnErrorOnFailure(calendarPeriods.Decode(reader));
140+
}
141+
142+
SetCalendarPeriod(date, calendarPeriods);
143+
144+
if (root.hasValue("SpecialDays"))
145+
{
146+
Json::FastWriter writer;
147+
const std::string json = writer.write(root["SpecialDays"]);
148+
149+
TLV::TLVReader reader;
150+
reader.Init(json);
151+
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::AnonymousTag()));
152+
ReturnErrorOnFailure(specialDays.Decode(reader));
153+
}
154+
155+
SetSpecialDays(specialDays);
156+
157+
if (root.hasValue("CurrentDay"))
158+
{
159+
Json::FastWriter writer;
160+
const std::string json = writer.write(root["CurrentDay"]);
161+
162+
TLV::TLVReader reader;
163+
reader.Init(json);
164+
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
165+
ReturnErrorOnFailure(currentDay.Decode(reader));
166+
}
167+
168+
if (root.hasValue("NextDay"))
169+
{
170+
Json::FastWriter writer;
171+
const std::string json = writer.write(root["NextDay"]);
172+
173+
TLV::TLVReader reader;
174+
reader.Init(json);
175+
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
176+
ReturnErrorOnFailure(nextDay.Decode(reader));
177+
}
178+
179+
SetCurrentAndNextDays(currentDay, nextDay);
180+
181+
if (root.hasValue("CurrentPeak"))
182+
{
183+
Json::FastWriter writer;
184+
const std::string json = writer.write(root["CurrentPeak"]);
185+
186+
TLV::TLVReader reader;
187+
reader.Init(json);
188+
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
189+
ReturnErrorOnFailure(currentPeak.Decode(reader));
190+
}
191+
192+
if (root.hasValue("NextPeak"))
193+
{
194+
Json::FastWriter writer;
195+
const std::string json = writer.write(root["NextPeak"]);
196+
197+
TLV::TLVReader reader;
198+
reader.Init(json);
199+
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
200+
ReturnErrorOnFailure(nextPeak.Decode(reader));
201+
}
202+
203+
SetPeakPeriods(currentPeak, nextPeak);
204+
205+
return CHIP_NO_ERROR;
206+
}
207+
208+
void CalendarProviderInstance::UpdateDays(uint32_t time)
209+
{
210+
211+
}
212+
213+
void CalendarProviderInstance::MoveToNextDay(void)
214+
{
215+
216+
}
217+
218+
void CalendarProviderInstance::UpdatePeak(uint32_t time)
219+
{
220+
221+
}
222+
223+
void CalendarProviderInstance::MoveToNextPeak(void)
224+
{
225+
226+
}
227+
228+
Protocols::InteractionModel::Status CalendarProviderInstance::GetDays(EndpointId ep, DataModel::Nullable<Structs::DayStruct::Type> &CurrentDay,
229+
DataModel::Nullable<Structs::DayStruct::Type> &NextDay)
230+
{
231+
CurrentDay = content.currentDay;
232+
NextDay = content.NextDay;
233+
234+
return CHIP_NO_ERROR;
235+
}
236+
237+
DataModel::Nullable<Structs::DayStruct::Type> CalendarProviderInstance::GetDay(uint32_t date)
238+
{
239+
auto days_iterator = context.SpecialDays.begin();
240+
while (days_iterator.Next())
241+
{
242+
auto & day = days_iterator.GetValue();
243+
if (day == currentDate)
244+
{
245+
return day;
246+
}
247+
}
248+
249+
TransitionDayOfWeekBitmap week_day = GetWeekDate(date);
250+
251+
auto period_iterator = context.CalendarPeriods.begin();
252+
while (period_iterator.Next())
253+
{
254+
auto & period = period_iterator.GetValue();
255+
if (period.StartDate < date)
256+
continue;
257+
auto days_iterator = period.Days.begin();
258+
while (days_iterator.Next())
259+
{
260+
auto & day = days_iterator.GetValue();
261+
if ((day.DaysOfWeek & week_day != 0) || (day.Date == date))
262+
{
263+
return day;
264+
}
265+
}
266+
}
267+
268+
return DataModel::Nullable<Structs::DayStruct::Type>();
269+
}
270+
271+
#if 0
272+
CHIP_ERROR EnergyCalendarContent::UpdateDateRelativeAttributes()
273+
{
274+
uint32_t date = get_current_utc();
275+
//uint32_t time = date % kOneDay;
276+
//date -= time;
277+
278+
if ((currentDate <= date) && (date < currentDate + kOneDay))
279+
{
280+
return CHIP_NO_ERROR;
281+
}
282+
283+
currentDate = date;
284+
CurrentDay = nullptr;
285+
NextDay = nullptr;
286+
CurrentTransition = nullptr;
287+
//CurrentPeakPeriod = nullptr;
288+
//NextPeakPeriod = nullptr;
289+
290+
CurrentDay = EnergyCalendarContent::GetDay(date);
291+
if (!CurrentDay.IsNull())
292+
{
293+
auto &day = CurrentDay.Value();
294+
currentDate = day.Date;
295+
auto transition_iterator = day.Transitions.begin();
296+
uint32_t next_tr_time = kOneDay;
297+
298+
while (transition_iterator.Next())
299+
{
300+
auto & transition = transition_iterator.GetValue();
301+
auto tr_time = transition.TransitionTime;
302+
if (tr_time <= time && (CurrentTransition == nullptr || CurrentTransition.TransitionTime < tr_time))
303+
{
304+
CurrentTransition = transition;
305+
}
306+
if ((time > tr_time) && (time < next_tr_time))
307+
{
308+
next_tr_time = time;
309+
}
310+
}
311+
312+
//CurrentPeakPeriod.Value() = DayToPeak(day);
313+
}
314+
315+
NextDay = EnergyCalendarContent::GetDay(date + kOneDay);
316+
//if (!NextDay.IsNull())
317+
//{
318+
// NexytPeakPeriod.Value() = DayToPeak(NextDay.Value());
319+
//}
320+
321+
return CHIP_NO_ERROR;
322+
}
323+
324+
#endif
325+
326+
bool CalendarProviderInstance::CheckPeriods(DataModel::DecodableList<Structs::CalendarPeriod::Type> periods)
327+
{
328+
uint32_t date = 0;
329+
auto period_iterator = periods.begin();
330+
while (period_iterator.Next())
331+
{
332+
auto & period = period_iterator.GetValue();
333+
if (period.StartDate)
334+
{
335+
if (period.StartDate < date)
336+
{
337+
return false;
338+
}
339+
date = period.StartDate;
340+
}
341+
342+
auto days_iterator = period.Days.begin();
343+
while (days_iterator.Next())
344+
{
345+
auto & day = days_iterator.GetValue();
346+
if (!CheckDay(day))
347+
{
348+
return false;
349+
}
350+
}
351+
}
352+
353+
return true;
354+
}
355+
356+
bool CalendarProviderInstance::CheckSpecialDays(DataModel::DecodableList<Structs::DayStruct::Type> days)
357+
{
358+
uint32_t date = 0;
359+
while (days_iterator.Next())
360+
auto days_iterator = days.begin();
361+
{
362+
auto & day = days_iterator.GetValue();
363+
if (day.DaysOfWeek || day.CalendarID || !CheckDay(day) || !(day.date) || day.date > date)
364+
{
365+
return false;
366+
}
367+
date = day.date;
368+
}
369+
370+
return true;
371+
}
372+
373+
bool CalendarProviderInstance::CheckDay(const Structs::DayStruct::Type &day)
374+
{
375+
if (day.DaysOfWeek && day.Date) || (!day.DaysOfWeek && !day.Date))
376+
{
377+
return false;
378+
}
379+
380+
if (size(day.Transition)== 0)
381+
{
382+
return false;
383+
}
384+
385+
uint32_t time = 0;
386+
auto transition_iterator day.Transitions.begin();
387+
while (transition_iterator.Next())
388+
{
389+
auto & transition = transition_iterator.GetValue();
390+
auto tr_time = transition.TransitionTime;
391+
if (tr_time < time)
392+
{
393+
return false;
394+
}
395+
time = tr_time;
396+
}
397+
398+
return true;
399+
}

0 commit comments

Comments
 (0)