Skip to content

Commit

Permalink
✨ Add fluent API, complete docs, and update example
Browse files Browse the repository at this point in the history
  • Loading branch information
marvinroger committed Nov 9, 2017
1 parent a48cb26 commit 498f58a
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 66 deletions.
81 changes: 67 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,41 +30,94 @@ to make the shutters go halfway (50%) for example. So I built this library.

See examples folder for examples.

#### Shutters (void (\*`upCallback`)(void), void (\*`downCallback`)(void), void (\*`haltCallback`)(void), byte (\*`getStateCallback`)(void), void (\*`setStateCallback`)(byte state))
#### Shutters (void (\*`upCallback`)(Shutters* shutters), void (\*`downCallback`)(Shutters* shutters), void (\*`haltCallback`)(Shutters* shutters), const char* (\*`getStateCallback`)(Shutters* shutters, byte length), void (\*`setStateCallback`)(Shutters* shutters, const char* state, byte length))

* **`upCallback()`**: Function to execute for the shutters to go up
* **`downCallback()`**: Function to execute for the shutters to go down
* **`haltCallback()`**: Function to execute for the shutters to halt
* **`getStateCallback()`**: Function to get state. This must return the state byte, or 255 if you don't know the state byte (on first boot)
* **`setStateCallback(byte state)`**: Function to set the state byte. Store this in the EEPROM of SPIFFS, etc.
* **`getStateCallback()`**: Function called to get the stored state. This must return the state char array of the given length
* **`setStateCallback()`**: Function called to set the stored state. Store this in the EEPROM of SPIFFS, etc.

#### void .begin ()
#### Shutters& .begin ()

Setup the shutters. Must be called once in `setup()`.
Setup the shutters.

#### void .setLevel (byte `percentage`)
Must be called once in `setup()`, after `setCourseTime()`, otherwise it won't have any effect.

Put the shutters to the given position.
#### Shutters& .loop ()

Handle the shutters.

Must be called in `loop()`. **Don't call `delay()` in loop() as it will block the loop, so Shutters will malfunction.**

#### unsigned long .getUpCourseTime ()

Returns the up course time or `0` if not yet `begin()`.

#### unsigned long .getDownCourseTime ()

Returns the down course time or `0` if not yet `begin()`.

#### Shutters& .setCourseTime (unsigned long `upCourseTime`, unsigned long `downCourseTime` = 0)

Set the course time. If `downCourseTime` is not set, it will be the same as `upCourseTime`.

Must be called at least one time, before `setup()`. Calling it after `setup()` will have no effect (unless `reset()` has been called).

* **`upCourseTime`**: Up course time, in milliseconds. Must be max 67108864, otherwise it will have no effect
* **`downCourseTime`**: Down course time, in milliseconds. Must be max 67108864, otherwise it will have no effect

#### float .getCalibrationRatio ()

Returns the calibration ration.

#### Shutters& .setCalibrationRatio (float `calibrationRatio` = 0)

Set the course time. If `downCourseTime` is not set, it will be the same as `upCourseTime`.

Can be called anytime, takes effect immediately.

* **`calibrationRatio`**: Calibration ratio. E.g. `0.5` means "50% of the course time". For example, if your course time is `10000`, and the calibration ratio is `0.2`, then, when we `setLevel()` to `0` or `100`, the shutters will move for `0.2 * 10000 = 2000`ms more than normal. That way, we can ensure we are actually at `0` or `100` and thus, that we are calibrated.

### Shutters& onLevelReached(void (\*`levelReachedCallback`)(Shutters* shutters, byte level))

Set the level reached handler. This handler will be called whenever a new level is reached, along with intermediary levels. E.g. if the levels are at 10% and you request 15%, the callback will be called for 11, 12, 13, 14 and 15%.

Can be called anytime, takes effect immediately.

* **`levelReachedCallback`**: Level reached callback

#### Shutters& .setLevel (byte `percentage`)

Put the shutters in the given position.
Note that if `percentage` == 0 || `percentage` == 100, the shutters will recalibrate (relays will stay active a bit longer than it should to ensure the shutters are really at their minimum or maximum position).

Can only be called after `begin()`, otherwise it won't have any effect.

* **`percentage`**: Percentage the shutters must go to. If not 0 <= `percentage` <= 100, nothing will be done

#### void .stop ()
#### Shutters& .stop ()

Stop the shutters.

Can only be called after `begin()`, otherwise it won't have any effect.

#### bool .isIdle ()

Return whether the shutters are currently idle or not.

#### void .loop ()

Handle the shutters. Must be called in `loop()`. **Don't call `delay()` in loop() as it will block the loop, so Shutters will malfunction.**

#### byte .getCurrentLevel ()

Return the current level of the shutters. Might be +/- 1% if the shutters are moving.

#### void .reset ()
#### Shutters& .reset ()

Erase saved state, for example for a reset routine. This disables the library, until you call `setCourseTime()` and `begin()` again.

#### Shutters& .isReset ()

Return whether the shutters is currently in a reset state or not (e.g. before having called `setCourseTime()` and `begin()`, or after a `reset()`).

## Behavior when changing course time

Erase saved state, for example for a reset routine. This disables the library, so don't forget to restart/reset the Arduino.
The stored state does contain the up and down course time, along with whether or not the current level is known, and if so, along with the current level. This means that if you change the course time after boot (or after `reset()`) with a course time that is not the same as the last known one, the shutters will auto-reset. In other words: you don't have to reset the state if you change the course time, everything is handled internally.
26 changes: 14 additions & 12 deletions examples/BasicShutters/BasicShutters.ino
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include <Shutters.h>
#include <EEPROM.h>

const uint8_t eepromOffset = 0;
const uint64_t upCourseTime = 30 * 1000;
const uint64_t downCourseTime = 45 * 1000;
const byte eepromOffset = 0;
const unsigned long upCourseTime = 30 * 1000;
const unsigned long downCourseTime = 45 * 1000;
const float calibrationRatio = 0.1;

void shuttersUp(Shutters* shutters) {
Expand All @@ -21,7 +21,7 @@ void shuttersHalt(Shutters* shutters) {
// TODO: Implement the code for the shutters to halt
}

char* shuttersGetState(Shutters* shutters, uint8_t length) {
char* shuttersGetState(Shutters* shutters, byte length) {
char state[length + 1];
for (uint8_t i = 0; i < length; i++) {
state[i] = EEPROM.read(eepromOffset + i);
Expand All @@ -31,16 +31,16 @@ char* shuttersGetState(Shutters* shutters, uint8_t length) {
return strdup(state);
}

void shuttersSetState(Shutters* shutters, const char* state, uint8_t length) {
for (uint8_t i = 0; i < length; i++) {
void shuttersSetState(Shutters* shutters, const char* state, byte length) {
for (byte i = 0; i < length; i++) {
EEPROM.write(eepromOffset + i, state[i]);
#ifdef ESP8266
EEPROM.commit();
#endif
}
}

void onShuttersLevelReached(Shutters* shutters, uint8_t level) {
void onShuttersLevelReached(Shutters* shutters, byte level) {
Serial.print("Shutters at ");
Serial.print(level);
Serial.println("%");
Expand All @@ -54,11 +54,13 @@ void setup() {
#ifdef ESP8266
EEPROM.begin(512);
#endif
Serial.println("Starting");
shutters.setCourseTime(upCourseTime, downCourseTime);
shutters.begin();

shutters.setLevel(50); // Go to 50%
Serial.println();
Serial.println("*** Starting ***");
shutters
.setCourseTime(upCourseTime, downCourseTime)
.onLevelReached(onShuttersLevelReached)
.begin()
.setLevel(30); // Go to 50%
}

void loop() {
Expand Down
3 changes: 2 additions & 1 deletion keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ Shutters KEYWORD1
#######################################

getUpCourseTime KEYWORD2
setCourseTime KEYWORD2
getDownCourseTime KEYWORD2
setCourseTime KEYWORD2
getCalibrationRatio KEYWORD2
setCalibrationRatio KEYWORD2
onLevelReached KEYWORD2
Expand All @@ -21,6 +21,7 @@ loop KEYWORD2
isIdle KEYWORD2
getCurrentLevel KEYWORD2
reset KEYWORD2
isReset KEYWORD2

#######################################
# Constants (LITERAL1)
Expand Down
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "Shutters",
"version": "2.1.1",
"version": "3.0.0-beta.1",
"keywords": "shutters, relays",
"description": "Allows non-smart roller-shutters to be percentage-controlled using time",
"homepage": "https://github.com/marvinroger/arduino-shutters",
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=Shutters
version=2.1.1
version=3.0.0-beta.1
author=Marvin ROGER
maintainer=Marvin ROGER
sentence=Allows non-smart roller-shutters to be percentage-controlled using time
Expand Down
Loading

0 comments on commit 498f58a

Please sign in to comment.