-
Notifications
You must be signed in to change notification settings - Fork 189
/
EvChargerController.cs
69 lines (60 loc) · 2.85 KB
/
EvChargerController.cs
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
// Copyright 2022 Jon Skeet. All rights reserved.
// Use of this source code is governed by the Apache License 2.0,
// as found in the LICENSE.txt file.using NodaTime;
using Microsoft.Extensions.Logging;
using NodaTime;
using NodaTime.Text;
namespace EvChargerTiming;
public class EvChargerController
{
// Note: Noda Time exposes a ZonedClock which could be used for this,
// which just composes a clock and a zone, but I've separated them out for
// clarity.
private readonly DateTimeZone zone;
private readonly IClock clock;
private readonly ChargingSchedule schedule;
private readonly EvCharger charger;
private readonly ILogger logger;
public EvChargerController(EvCharger charger, ChargingSchedule schedule, DateTimeZone zone, IClock clock, ILogger logger)
{
this.charger = charger;
this.schedule = schedule;
this.zone = zone;
this.clock = clock;
this.logger = logger;
}
/// <summary>
/// Infinite loop which just checks periodically whether the charger should be on or not,
/// based on the schedule.
/// </summary>
/// <param name="pollingInterval">The interval at which to check whether or not the charger should be on.</param>
public void MainLoop(TimeSpan pollingInterval)
{
// In a real system we'd want ways of shutting down, updating the schedule,
// changing the target time zone, updating the time zone database etc.
while (true)
{
Instant now = clock.GetCurrentInstant();
// Note: converting an instant into a local date/time is always unambiguous. (Every
// instant maps to exactly one local date/time.) Conversions in the opposite
// direction may be ambiguous or invalid.
ZonedDateTime nowInTimeZone = now.InZone(zone);
bool shouldBeOn = schedule.IsChargingEnabled(nowInTimeZone.LocalDateTime);
if (charger.On != shouldBeOn)
{
logger.LogInformation("At {now} ({local} local), changing state to {state}",
InstantPattern.ExtendedIso.Format(now),
ZonedDateTimePattern.GeneralFormatOnlyIso.Format(nowInTimeZone),
shouldBeOn);
charger.ChangeState(shouldBeOn);
}
// We *could* predict when we'll next need to turn the charger on.
// However, that's significantly more fiddly than just checking periodically.
// A check of something "once per minute" will take very little power,
// and be much simpler than trying to predict how long to sleep for.
// The reality of EV charging is that we don't need to be massively accurate here;
// sleeping for several seconds or even a few minutes between checks should be fine.
Thread.Sleep(pollingInterval);
}
}
}