Skip to content

CloudSchedule #284

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 27 commits into from
Dec 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
30cfea3
Initial scheduler implementation
pennam Oct 5, 2021
dd0ccf5
Initial Scheduler tests
pennam Oct 6, 2021
5c30e04
Add tests for x minutes and weekly schedule
pennam Oct 7, 2021
e827383
Scheduler property refactoring
pennam Oct 26, 2021
a3a739e
Add monthly yearly and oneshot schedule tests
pennam Oct 26, 2021
a8e1a77
Fix typo in comment
pennam Oct 27, 2021
116851f
Rename property Scheduler/CloudScheduler to Schedule/CloudSchedule
pennam Oct 27, 2021
b75b8cd
Add isActive method to CloudSchedule
pennam Oct 27, 2021
76647d9
Rename CloudSchedule fields from start end duration mask to frm to le…
pennam Oct 28, 2021
089a633
CloudSchedule refactor
pennam Nov 3, 2021
5af2f89
Add encode and decode test
pennam Nov 4, 2021
e901a85
Add example sketch for CloudSchedule property
pennam Nov 9, 2021
e2b9526
Add properties and logic to handle timezone and dst changes
pennam Nov 2, 2021
a52d001
Add TimeService::getLocalTime() fake to unit tests
pennam Nov 17, 2021
74cf0b2
Add DEBUG_DEBUG print to keep track of offset and dst_until changes
pennam Nov 12, 2021
394da9a
Add functions to ease Schedule configuration
pennam Nov 15, 2021
c035af8
Add getTimeFromString() function to convert an input string into a Sc…
pennam Nov 15, 2021
d4cfdd6
Update example adding all schedules types and using schedule configur…
pennam Nov 15, 2021
14736a1
Make TimeService instance reusable
pennam Nov 25, 2021
4bbe087
Add check for valid time
pennam Nov 25, 2021
d5a676a
Return a valid localtime only if timezone is configured and initializ…
pennam Nov 25, 2021
cb39907
Do not store EPOCH_AT_COMPILE_TIME into the RTC
pennam Nov 25, 2021
0776f4b
Use correct destination type when casting enums
pennam Nov 29, 2021
028c299
Use ScheduleTimeType and ScheduleConfigurationType instead of unsigne…
pennam Nov 29, 2021
d42e419
Move TimeService::getLocalTime() into CloudSchedule test file to make…
pennam Nov 30, 2021
71059d0
Make ArduinoIoTCloudTimeService return a reference instead of a pointer
pennam Nov 30, 2021
fda11b5
Add ArduinoIoTCloudClass CTOR and initialize variables in it
pennam Dec 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 230 additions & 0 deletions examples/ArduinoIoTCloud-Schedule/ArduinoIoTCloud-Schedule.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/*
This sketch demonstrates how to use the cloud schedule variable type.

This sketch is compatible with the following boards:
- MKR 1000
- MKR WIFI 1010
- MKR GSM 1400
- MKR NB 1500
- MKR WAN 1300/1310
- Nano 33 IoT
- ESP 8266
*/

#include "arduino_secrets.h"
#include "thingProperties.h"

#if defined(ESP32)
static int const LED_BUILTIN = 2;
#endif

void setup() {
/* Initialize the serial port and wait up to 5 seconds for a connection */
Serial.begin(9600);
for(unsigned long const serialBeginTime = millis(); !Serial && (millis() - serialBeginTime > 5000); ) { }

/* Configure LED pin as an output */
pinMode(LED_BUILTIN, OUTPUT);

/* This function takes care of connecting your sketch variables to the ArduinoIoTCloud object */
initProperties();

/* Initialize Arduino IoT Cloud library */
ArduinoCloud.begin(ArduinoIoTPreferredConnection);

setDebugMessageLevel(DBG_INFO);
ArduinoCloud.printDebugInfo();

/* Setup one shot schedule example */
setupOneShotSchedule();

/* Setup per minute schedule example */
setupMinuteSchedule();

/* Setup hourly schedule example */
setupHourlySchedule();

/* Setup daily schedule example */
setupDailySchedule();

/* Setup weekly schedule example */
setupWeeklySchedule();

/* Setup monthly schedule example */
setupMonthlySchedule();

/* Setup yearly schedule example */
setupYearlySchedule();
}

/* Setup a schedule with an active period of 5 minutes that doesn't repeat
* Starting from 2021 11 01 17:00:00
* Until 2021 11 02 17:00:00
*/
void setupOneShotSchedule() {

ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00");
ScheduleTimeType until = startingFrom + ( DAYS * 1 );
ScheduleTimeType activePeriod = MINUTES * 5;

/* Warning: there is no cross check between until and activePeriod */
ScheduleConfigurationType scheduleConfiguration = Schedule::createOneShotScheduleConfiguration();

oneShot = Schedule(startingFrom, until, activePeriod, scheduleConfiguration);
}

/* Setup a schedule with an active period of 15 seconds that repeats each minute
* Starting from 2021 11 01 17:00:00
* Until 2021 11 02 17:00:00
*/
void setupMinuteSchedule() {

ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00");
ScheduleTimeType until = startingFrom + ( DAYS * 1 );
ScheduleTimeType activePeriod = SECONDS * 15;
unsigned int repetitionPeriod = 1;

/* Warning: there is no cross check between repetitionPeriod and activePeriod */
ScheduleConfigurationType scheduleConfiguration = Schedule::createFixedDeltaScheduleConfiguration(ScheduleUnit::Minutes, repetitionPeriod);

minute = Schedule(startingFrom, until, activePeriod, scheduleConfiguration);
}

/* Setup a schedule with an active period of 20 minutes that repeats each hour
* Starting from 2021 11 01 17:00:00
* Until 2021 11 15 13:00:00
*/
void setupHourlySchedule() {

ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00");
ScheduleTimeType until = TimeService::getTimeFromString("2021 Nov 15 13:00:00");
ScheduleTimeType activePeriod = MINUTES * 20;
unsigned int repetitionPeriod = 1;

/* Warning: there is no cross check between repetitionPeriod and activePeriod */
ScheduleConfigurationType scheduleConfiguration = Schedule::createFixedDeltaScheduleConfiguration(ScheduleUnit::Hours, repetitionPeriod);

hourly = Schedule(startingFrom, until, activePeriod, scheduleConfiguration);
}

/* Setup a schedule with an active period of 2 hours that repeats each day
* Starting from 2021 11 01 17:00:00
* Until 2021 11 15 13:00:00
*/
void setupDailySchedule() {

ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00");
ScheduleTimeType until = TimeService::getTimeFromString("2021 Nov 15 13:00:00");
ScheduleTimeType activePeriod = HOURS * 2;
unsigned int repetitionPeriod = 1;

/* Warning: there is no cross check between repetitionPeriod and activePeriod */
ScheduleConfigurationType scheduleConfiguration = Schedule::createFixedDeltaScheduleConfiguration(ScheduleUnit::Days, repetitionPeriod);

daily = Schedule(startingFrom, until, activePeriod, scheduleConfiguration);
}

/* Setup a schedule with an active period of 3 minutes with a weekly configuration
* Starting from 2021 11 01 17:00:00
* Until 2021 11 31 17:00:00
* Weekly configuration
* Sunday -> Inactive
* Monday -> Active
* Tuesday -> Inactive
* Wednesday -> Active
* Thursday -> Inactive
* Friday -> Active
* Saturday -> Inactive
*/
void setupWeeklySchedule() {

unsigned int startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00");
unsigned int until = startingFrom + ( DAYS * 30 );
unsigned int executionPeriod = MINUTES * 3;

ScheduleWeeklyMask WeeklyMask = {
ScheduleState::Inactive, /* Sunday */
ScheduleState::Active, /* Monday */
ScheduleState::Inactive, /* Tuesday */
ScheduleState::Active, /* Wednesday */
ScheduleState::Inactive, /* Thursday */
ScheduleState::Active, /* Friday */
ScheduleState::Inactive, /* Saturday */
};

ScheduleConfigurationType scheduleConfiguration = Schedule::createWeeklyScheduleConfiguration(WeeklyMask);

weekly = Schedule(startingFrom, until, executionPeriod, scheduleConfiguration);
}

/* Setup a schedule with an active period of 1 day that repeats each third day of the month
* Starting from 2021 11 01 17:00:00
* Until 2022 11 15 13:00:00
*/
void setupMonthlySchedule() {

ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 01 17:00:00");
ScheduleTimeType until = TimeService::getTimeFromString("2021 Nov 15 13:00:00");
ScheduleTimeType activePeriod = DAYS * 1;
int dayOfMonth = 3;

ScheduleConfigurationType scheduleConfiguration = Schedule::createMonthlyScheduleConfiguration(dayOfMonth);

monthly = Schedule(startingFrom, until, activePeriod, scheduleConfiguration);
}


/* Setup a schedule with an active period of 2 days that repeats each year on November 6th
* Starting from 2021 11 06 17:00:00
* Until 2041 11 15 13:00:00
*/
void setupYearlySchedule() {

ScheduleTimeType startingFrom = TimeService::getTimeFromString("2021 Nov 06 17:00:00");
ScheduleTimeType until = TimeService::getTimeFromString("2041 Nov 06 13:00:00");
ScheduleTimeType activePeriod = DAYS * 2;
int dayOfMonth = 6;

ScheduleConfigurationType scheduleConfiguration = Schedule::createYearlyScheduleConfiguration(ScheduleMonth::Nov, dayOfMonth);

yearly = Schedule(startingFrom, until, activePeriod, scheduleConfiguration);
}

void loop() {
ArduinoCloud.update();

/* Print a message when the oneShot schedule is active */
if(oneShot.isActive()) {
Serial.println("One shot schedule is active");
}

/* Print a message when the per minute schedule is active */
if(minute.isActive()) {
Serial.println("Per minute schedule is active");
}

/* Print a message when the hourly schedule is active */
if(hourly.isActive()) {
Serial.println("Hourly schedule is active");
}

/* Print a message when the daily schedule is active */
if(daily.isActive()) {
Serial.println("Daily schedule is active");
}

/* Activate LED when the weekly schedule is active */
digitalWrite(LED_BUILTIN, weekly.isActive());

/* Print a message when the monthly schedule is active */
if(monthly.isActive()) {
Serial.println("Monthly schedule is active");
}

/* Print a message when the yearly schedule is active */
if(yearly.isActive()) {
Serial.println("Yearly schedule is active");
}

}

34 changes: 34 additions & 0 deletions examples/ArduinoIoTCloud-Schedule/arduino_secrets.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <Arduino_ConnectionHandler.h>

/* MKR1000, MKR WiFi 1010 */
#if defined(BOARD_HAS_WIFI)
#define SECRET_SSID "YOUR_WIFI_NETWORK_NAME"
#define SECRET_PASS "YOUR_WIFI_PASSWORD"
#endif

/* ESP8266 */
#if defined(BOARD_ESP8266)
#define SECRET_DEVICE_KEY "my-device-password"
#endif

/* MKR GSM 1400 */
#if defined(BOARD_HAS_GSM)
#define SECRET_PIN ""
#define SECRET_APN ""
#define SECRET_LOGIN ""
#define SECRET_PASS ""
#endif

/* MKR WAN 1300/1310 */
#if defined(BOARD_HAS_LORA)
#define SECRET_APP_EUI ""
#define SECRET_APP_KEY ""
#endif

/* MKR NB 1500 */
#if defined(BOARD_HAS_NB)
#define SECRET_PIN ""
#define SECRET_APN ""
#define SECRET_LOGIN ""
#define SECRET_PASS ""
#endif
46 changes: 46 additions & 0 deletions examples/ArduinoIoTCloud-Schedule/thingProperties.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <ArduinoIoTCloud.h>
#include <Arduino_ConnectionHandler.h>

#define THING_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
#define BOARD_ID "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

void onSwitchButtonChange();

bool switchButton;
CloudSchedule oneShot;
CloudSchedule minute;
CloudSchedule hourly;
CloudSchedule daily;
CloudSchedule weekly;
CloudSchedule monthly;
CloudSchedule yearly;

void initProperties() {
#if defined(BOARD_ESP8266)
ArduinoCloud.setBoardId(BOARD_ID);
ArduinoCloud.setSecretDeviceKey(SECRET_DEVICE_KEY);
#endif
ArduinoCloud.setThingId(THING_ID);
#if defined(BOARD_HAS_WIFI) || defined(BOARD_HAS_GSM) || defined(BOARD_HAS_NB)
ArduinoCloud.addProperty(switchButton, WRITE, ON_CHANGE);
ArduinoCloud.addProperty(oneShot, READWRITE, ON_CHANGE);
ArduinoCloud.addProperty(minute, READWRITE, ON_CHANGE);
ArduinoCloud.addProperty(hourly, READWRITE, ON_CHANGE);
ArduinoCloud.addProperty(daily, READWRITE, ON_CHANGE);
ArduinoCloud.addProperty(weekly, READWRITE, ON_CHANGE);
ArduinoCloud.addProperty(monthly, READWRITE, ON_CHANGE);
ArduinoCloud.addProperty(yearly, READWRITE, ON_CHANGE);
#elif defined(BOARD_HAS_LORA)
ArduinoCloud.addProperty(switchButton, 1, WRITE, ON_CHANGE;
#endif
}

#if defined(BOARD_HAS_WIFI)
WiFiConnectionHandler ArduinoIoTPreferredConnection(SECRET_SSID, SECRET_PASS);
#elif defined(BOARD_HAS_GSM)
GSMConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS);
#elif defined(BOARD_HAS_LORA)
LoRaConnectionHandler ArduinoIoTPreferredConnection(SECRET_APP_EUI, SECRET_APP_KEY, _lora_band::EU868, NULL, _lora_class::CLASS_A);
#elif defined(BOARD_HAS_NB)
NBConnectionHandler ArduinoIoTPreferredConnection(SECRET_PIN, SECRET_APN, SECRET_LOGIN, SECRET_PASS);
#endif
2 changes: 2 additions & 0 deletions extras/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ include_directories(include)
include_directories(../../src)
include_directories(../../src/cbor)
include_directories(../../src/property)
include_directories(../../src/utility/time)
include_directories(external/catch/v2.12.1/include)
include_directories(external/fakeit/v2.0.5/include)

Expand All @@ -32,6 +33,7 @@ set(TEST_SRCS
src/test_callback.cpp
src/test_CloudColor.cpp
src/test_CloudLocation.cpp
src/test_CloudSchedule.cpp
src/test_decode.cpp
src/test_encode.cpp
src/test_publishEvery.cpp
Expand Down
14 changes: 14 additions & 0 deletions extras/test/include/Arduino_ConnectionHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
Copyright (c) 2019 Arduino. All rights reserved.
*/

#ifndef TEST_ARDUINO_CONNECTION_HANDLER_H_
#define TEST_ARDUINO_CONNECTION_HANDLER_H_

/******************************************************************************
TYPEDEF
******************************************************************************/

typedef void ConnectionHandler;

#endif /* TEST_ARDUINO_CONNECTION_HANDLER_H_ */
Loading