-
Notifications
You must be signed in to change notification settings - Fork 117
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new /limit API endpoint Added classes: Limit LimitProperties LimitType class POST { "type": type, "value": value, "auto_release" : optional bool } type actually possible are : 'time", "energy", "soc", "range" only time & energy are implemented. Disable state when time or energy session > defined limit. Release disable claim when car is disconnected. time_limit in minutes session_energy in w/h
- Loading branch information
Showing
4 changed files
with
410 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
#if defined(ENABLE_DEBUG) && !defined(ENABLE_DEBUG_LIMIT) | ||
#undef ENABLE_DEBUG | ||
#endif | ||
|
||
#include "limit.h" | ||
#include "debug.h" | ||
#include <Arduino.h> | ||
#include <ArduinoJson.h> | ||
#include <MicroTasks.h> | ||
#include "evse_man.h" | ||
|
||
// --------------------------------------------- | ||
// | ||
// LimitType Class | ||
// | ||
//---------------------------------------------- | ||
|
||
uint8_t LimitType::fromString(const char *value) | ||
{ | ||
// Cheat a bit and just check the first char | ||
switch (value[0]) { | ||
// None | ||
case ('n'): | ||
_value = LimitType::None; | ||
break; | ||
//Time | ||
case ('t'): | ||
_value = LimitType::Time; | ||
break; | ||
//Energy | ||
case ('e'): | ||
_value = LimitType::Energy; | ||
break; | ||
//Soc | ||
case ('s'): | ||
_value = LimitType::Soc; | ||
break; | ||
//Range | ||
case ('r'): | ||
_value = LimitType::Range; | ||
break; | ||
} | ||
return _value; | ||
} | ||
const char *LimitType::toString() | ||
{ | ||
return LimitType::None == _value ? "none" : | ||
LimitType::Time == _value ? "time" : | ||
LimitType::Energy == _value ? "energy" : | ||
LimitType::Soc == _value ? "soc" : | ||
LimitType::Range == _value ? "range" : | ||
"unknown"; | ||
} | ||
|
||
LimitType LimitType::operator= (const Value val) { | ||
_value = val; | ||
return *this; | ||
} | ||
|
||
// --------------------------------------------- | ||
// | ||
// LimitProperties Class | ||
// | ||
//---------------------------------------------- | ||
LimitProperties::LimitProperties() | ||
{ | ||
_type = LimitType::None; | ||
_value = 0; | ||
_auto_release = true; | ||
}; | ||
|
||
LimitProperties::~LimitProperties() | ||
{ | ||
DBUGLN("LimitProperties Destructor"); | ||
|
||
}; | ||
|
||
void LimitProperties::init() | ||
{ | ||
_type = LimitType::None; | ||
_value = 0; | ||
_auto_release = true; | ||
}; | ||
|
||
LimitType LimitProperties::getType() { | ||
return _type; | ||
}; | ||
|
||
bool LimitProperties::setType(LimitType type) | ||
{ | ||
_type = type; | ||
return true; | ||
}; | ||
|
||
uint32_t LimitProperties::getValue() { | ||
return _value; | ||
}; | ||
|
||
bool LimitProperties::setValue(uint32_t value) | ||
{ | ||
_value = value; | ||
return true; | ||
}; | ||
|
||
bool LimitProperties::getAutoRelease() { | ||
return _auto_release; | ||
}; | ||
|
||
bool LimitProperties::deserialize(JsonObject &obj) | ||
{ | ||
if(obj.containsKey("type")) { | ||
_type.fromString(obj["type"]); | ||
} | ||
if(obj.containsKey("value")) { | ||
_value = obj["value"]; | ||
} | ||
if(obj.containsKey("auto_release")) { | ||
_auto_release = obj["auto_release"]; | ||
} | ||
return _type > 0 && _value > 0; | ||
|
||
}; | ||
|
||
bool LimitProperties::serialize(JsonObject &obj) | ||
{ | ||
|
||
obj["type"] = _type.toString(); | ||
obj["value"] = _value; | ||
obj["auto_release"] = _auto_release; | ||
return true; | ||
}; | ||
|
||
// --------------------------------------------- | ||
// | ||
// Limit Class | ||
// | ||
//---------------------------------------------- | ||
|
||
//global instance | ||
Limit limit; | ||
|
||
Limit::Limit() : Limit::Task() { | ||
_limit_properties.init(); | ||
}; | ||
|
||
Limit::~Limit() { | ||
_evse -> release(EvseClient_OpenEVSE_Limit); | ||
}; | ||
|
||
void Limit::setup() { | ||
|
||
}; | ||
|
||
void Limit::begin(EvseManager &evse) { | ||
// todo get saved default limit | ||
DBUGLN("Starting Limit task"); | ||
this -> _evse = &evse; | ||
MicroTask.startTask(this); | ||
}; | ||
|
||
unsigned long Limit::loop(MicroTasks::WakeReason reason) { | ||
|
||
|
||
if (hasLimit()) { | ||
LimitType type = _limit_properties.getType(); | ||
uint32_t value = _limit_properties.getValue(); | ||
bool auto_release = _limit_properties.getAutoRelease(); | ||
|
||
if (_evse->isCharging() ) { | ||
_has_vehicle = true; | ||
bool limit_reached = false; | ||
switch (type) { | ||
case LimitType::Time: | ||
limit_reached = limitTime(value); | ||
break; | ||
case LimitType::Energy: | ||
limit_reached = limitEnergy(value); | ||
break; | ||
} | ||
if (limit_reached) { | ||
// Limit reached, disabling EVSE | ||
if (_evse->getClaimProperties(EvseClient_OpenEVSE_Limit).getState() == EvseState::None) { | ||
DBUGLN("Limit as expired, disable evse"); | ||
EvseProperties props; | ||
props.setState(EvseState::Disabled); | ||
props.setAutoRelease(true); | ||
_evse->claim(EvseClient_OpenEVSE_Limit, EvseManager_Priority_Limit, props); | ||
} | ||
} | ||
|
||
} | ||
else if ( _has_vehicle && !_evse->isVehicleConnected()) { | ||
_has_vehicle = false; | ||
// if auto release is set, reset Limit properties | ||
if (auto_release) { | ||
_limit_properties.init(); | ||
} | ||
} | ||
|
||
} | ||
|
||
return EVSE_LIMIT_LOOP_TIME; | ||
}; | ||
|
||
bool Limit::limitTime(uint32_t val) { | ||
if ( val != 0 && _evse->getSessionElapsed() > 0 && _evse->getSessionElapsed()/60 >= val ) { | ||
// Time limit done | ||
return false; | ||
} | ||
else return true; | ||
}; | ||
|
||
bool Limit::limitEnergy(uint32_t val) { | ||
if ( val != 0 && _evse->getSessionEnergy() > 0 && (uint32_t)_evse->getSessionEnergy() >= val ) { | ||
// Time limit done | ||
return false; | ||
} | ||
else return true; | ||
}; | ||
|
||
bool Limit::hasLimit() { | ||
return _limit_properties.getType() != LimitType::None; | ||
}; | ||
|
||
bool Limit::set(String json) { | ||
LimitProperties props; | ||
if (props.deserialize(json)) { | ||
set(props); | ||
return true; | ||
} | ||
else return false; | ||
}; | ||
|
||
bool Limit::set(LimitProperties props) { | ||
_limit_properties = props; | ||
return true; | ||
}; | ||
|
||
bool Limit::clear() { | ||
_limit_properties.init(); | ||
return true; | ||
}; | ||
|
||
LimitProperties Limit::getLimitProperties() { | ||
return _limit_properties; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
#ifndef _OPENEVSE_LIMIT_H | ||
#define _OPENEVSE_LIMIT_H | ||
|
||
|
||
#ifndef EVSE_LIMIT_LOOP_TIME | ||
#define EVSE_LIMIT_LOOP_TIME 1000 | ||
#endif | ||
#include <Arduino.h> | ||
#include <ArduinoJson.h> | ||
#include <MicroTasks.h> | ||
#include "evse_man.h" | ||
|
||
class LimitType { | ||
|
||
public: | ||
enum Value : uint8_t { | ||
None, | ||
Time, | ||
Energy, | ||
Soc, | ||
Range | ||
}; | ||
|
||
LimitType() = default; | ||
constexpr LimitType(Value value) : _value(value) { } | ||
uint8_t fromString(const char *value); | ||
const char *toString(); | ||
|
||
operator Value() const { return _value; } | ||
explicit operator bool() = delete; // Prevent usage: if(state) | ||
LimitType operator= (const Value val); | ||
|
||
private: | ||
Value _value; | ||
}; | ||
|
||
class LimitProperties : virtual public JsonSerialize<512> { | ||
private: | ||
LimitType _type; | ||
uint32_t _value; | ||
bool _auto_release; | ||
public: | ||
LimitProperties(); | ||
~LimitProperties(); | ||
void init(); | ||
bool setType(LimitType type); | ||
bool setValue(uint32_t value); | ||
LimitType getType(); | ||
uint32_t getValue(); | ||
bool getAutoRelease(); | ||
|
||
using JsonSerialize::deserialize; | ||
virtual bool deserialize(JsonObject &obj); | ||
using JsonSerialize::serialize; | ||
virtual bool serialize(JsonObject &obj); | ||
|
||
}; | ||
|
||
class Limit: public MicroTasks::Task | ||
{ | ||
private: | ||
EvseManager *_evse; | ||
LimitProperties _limit_properties; | ||
bool _has_vehicle; | ||
bool limitTime(uint32_t val); | ||
bool limitEnergy(uint32_t val); | ||
bool limitSoc(uint32_t val); | ||
bool limitRange(uint32_t val); | ||
|
||
protected: | ||
void setup(); | ||
unsigned long loop(MicroTasks::WakeReason reason); | ||
|
||
|
||
public: | ||
Limit(); | ||
~Limit(); | ||
void begin(EvseManager &evse); | ||
bool hasLimit(); | ||
bool set(String json); | ||
bool set(LimitProperties props); | ||
bool clear(); | ||
LimitProperties getLimitProperties(); | ||
}; | ||
|
||
extern Limit limit; | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.