-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDoorState.h
169 lines (136 loc) · 7.6 KB
/
DoorState.h
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#pragma once
/*
DoorState.h
DoorState is the definition of a class that handles a garage door and uses the StateTable library to maintain the door state and execute actions as
events occur. External events come from a transitory switch which is used to open / close and stop the door.
Further external events comne from a hormann UAP 1 controller that is used to get changes in door information (is closed / is open / light on)
The hormann UAP 1 is also used to control the door with commands to start opening, start closing, stop the door and to turn on the light.
Author: (c) M. Naylor 2022
History:
Ver 1.0 Initial version
*/
#include <stdint.h>
#include <MNRGBLEDBaseLib.h>
#include "InputPin.h"
#include "OutputPin.h"
#include <memory>
typedef uint8_t pin_size_t;
#ifndef NOT_A_PIN
const uint8_t NOT_A_PIN = 255;
#endif
// Colours used on MKR RGB LED to indicate status
constexpr RGBType STATE_UNKNOWN_COLOUR = MNRGBLEDBaseLib::WHITE;
constexpr RGBType DOOR_CLOSED_COLOUR = MNRGBLEDBaseLib::GREEN;
constexpr RGBType DOOR_OPEN_COLOUR = MNRGBLEDBaseLib::RED;
constexpr RGBType DOOR_STOPPED_COLOUR = MNRGBLEDBaseLib::DARK_MAGENTA;
constexpr RGBType DOOR_BAD_COLOUR = MNRGBLEDBaseLib::DARK_YELLOW;
constexpr RGBType DOOR_UNKNOWN_COLOUR = MNRGBLEDBaseLib::BLUE;
constexpr uint8_t DOOR_STATIONARY_FLASHTIME = 0;
constexpr uint8_t DOOR_MOVING_FLASHTIME = 10; // 20 = 1 sec
constexpr PinStatus RELAY_ON_VALUE = HIGH;
constexpr PinStatus RELAY_OFF = LOW;
class DoorStatusPin;
class DoorStatusCalc;
class DoorState
{
protected:
public:
DoorState ( pin_size_t OpenPin, pin_size_t ClosePin, pin_size_t StopPin, pin_size_t LightPin, pin_size_t DoorOpenStatusPin, pin_size_t DoorClosedStatusPin, pin_size_t DoorLightStatusPin, pin_size_t m_DoorSwitchStatusPin );
uint32_t GetLightOffCount () const;
uint32_t GetDoorOpenedCount () const;
uint32_t GetDoorOpeningCount () const;
uint32_t GetDoorClosedCount () const;
uint32_t GetDoorClosingCount () const;
void GetPinStates ( String &states );
void UpdateDoorState ();
enum State : uint8_t { Open = 0, Opening, Closed, Closing, Stopped, Unknown, Bad };
enum Direction : uint8_t { Up = 0, Down, None };
enum Event : uint8_t { DoorOpenTrue = 0, DoorOpenFalse, DoorClosedTrue, DoorClosedFalse, SwitchPress, Nothing };
enum Request : uint8_t { LightOn = 0, LightOff, OpenDoor, CloseDoor, StopDoor };
private:
void SetDoorDirection ( DoorState::Direction direction );
void SetDoorState ( DoorState::State newState );
// State table functions called when event occurs
void DoNowt ( Event ) {};
void NowOpen ( Event event );
void NowClosed ( Event event );
void NowClosing ( Event event );
void NowOpening ( Event event );
void SwitchPressed ( Event event );
typedef void ( DoorState::*StateFunction ) ( Event ); // prototype of function to handle event
const StateFunction StateTableFn[7][6] = { // State table of functions to call when event occurs. Order : [State][Event]
{ &DoorState::DoNowt, &DoorState::NowClosing, &DoorState::NowClosed, &DoorState::DoNowt, &DoorState::SwitchPressed, &DoorState::DoNowt }, // Actions when current state is Open
{ &DoorState::NowOpen, &DoorState::DoNowt, &DoorState::NowClosed, &DoorState::DoNowt, &DoorState::SwitchPressed, &DoorState::DoNowt }, // Actions when current state is Opening
{ &DoorState::NowOpen, &DoorState::DoNowt, &DoorState::DoNowt, &DoorState::NowOpening, &DoorState::SwitchPressed, &DoorState::DoNowt }, // Actions when current state is Closed
{ &DoorState::NowOpen, &DoorState::DoNowt, &DoorState::NowClosed, &DoorState::DoNowt, &DoorState::SwitchPressed, &DoorState::DoNowt }, // Actions when current state is Closing
{ &DoorState::NowOpen, &DoorState::DoNowt, &DoorState::NowClosed, &DoorState::DoNowt, &DoorState::SwitchPressed, &DoorState::DoNowt }, // Actions when current state is Stopped
{ &DoorState::NowOpen, &DoorState::NowClosing, &DoorState::NowClosed, &DoorState::NowOpening, &DoorState::SwitchPressed, &DoorState::DoNowt }, // Actions when current state is Unknown
{ &DoorState::NowOpen, &DoorState::NowClosing, &DoorState::NowClosed, &DoorState::NowOpening, &DoorState::SwitchPressed, &DoorState::DoNowt } // Actions when current state is Bad
};
const pin_size_t m_DoorOpenCtrlPin; // Used to request door is opened
const pin_size_t m_DoorCloseCtrlPin; // Used to request door is closed
const pin_size_t m_DoorStopCtrlPin; // Used to request door is stopped
const pin_size_t m_DoorLightCtrlPin; // Used to request light is turned on or off
const pin_size_t m_DoorOpenStatusPin; // Used to get status if door is open or not
const pin_size_t m_DoorClosedStatusPin; // Used to get status if door is closed or not
const pin_size_t m_DoorLightStatusPin; // Used to get status if door light is on or not
const pin_size_t m_DoorSwitchStatusPin; // Used to get status of switch press
std::unique_ptr<DoorStatusPin> m_pDoorOpenStatusPin = nullptr; // Objects to handle pins giving door status
std::unique_ptr<DoorStatusPin> m_pDoorClosedStatusPin = nullptr;
std::unique_ptr<DoorStatusPin> m_pDoorLightStatusPin = nullptr;
std::unique_ptr<DoorStatusPin> m_pDoorSwitchStatusPin = nullptr; // Object to handle switch press
DoorStatusCalc * m_pDoorStatus = nullptr; // Object to handle door status
volatile bool m_bDoorStateChanged = true;
volatile uint32_t m_ulSwitchPressedTime = 0UL;
std::unique_ptr<OutputPin> m_pDoorOpenCtrlPin = nullptr; // Objects to handle controlling door actions
std::unique_ptr<OutputPin> m_pDoorCloseCtrlPin = nullptr;
std::unique_ptr<OutputPin> m_pDoorStopCtrlPin = nullptr;
std::unique_ptr<OutputPin> m_pDoorLightCtrlPin = nullptr;
void ResetTimer ();
void TurnOffControlPins (); // bring low all pins controlling garage functions
public:
void DoEvent ( Event eEvent );
void DoRequest ( Request eRequest );
const char * GetDoorDisplayState ();
DoorState::State GetDoorState ();
DoorState::Direction GetDoorDirection ();
bool IsOpen ();
bool IsMoving ();
bool IsClosed ();
bool IsLit ();
const char * GetDoorDirectionName ();
bool IsSwitchConfigured () const;
uint32_t GetSwitchMatchCount() const;
void SwitchDebugStats ( String &result ) const;
uint32_t GetLightOnCount () const;
};
/// @brief DoorStatusPin is a type of InputPin that performs additional actions when the pin matches or fails to match the required state
class DoorStatusPin : public InputPin
{
public:
DoorStatusPin ( DoorState *pDoor, DoorState::Event matchEvent, DoorState::Event unmatchEvent, pin_size_t pin, uint32_t debouncems, uint32_t maxMatchedTimems, PinStatus matchStatus, PinMode mode = PinMode::INPUT, PinStatus status = PinStatus::CHANGE );
private:
DoorState *m_pDoor;
DoorState::Event m_doorMatchEvent;
DoorState::Event m_doorUnmatchEvent;
void MatchAction ();
void UnmatchAction ();
};
/// @brief sets the door status based on current input pin readings from UAP and prior state
class DoorStatusCalc
{
public:
DoorStatusCalc ( DoorStatusPin &openPin, DoorStatusPin &closePin );
void UpdateStatus ();
DoorState::State GetDoorState ();
void SetDoorState ( DoorState::State state );
DoorState::Direction GetDoorDirection ();
void SetDoorDirection ( DoorState::Direction direction );
const char *GetDoorDirectionName ();
void SetStopped ();
private:
DoorStatusPin &m_openPin;
DoorStatusPin &m_closePin;
volatile DoorState::State m_currentState;
volatile DoorState::Direction m_LastDirection = DoorState::Direction::None;
};