@@ -35,6 +35,8 @@ ConnectorStatus::ConnectorStatus(OcppModel& context, int connectorId)
3535
3636 connectionTimeOut = declareConfiguration<int >(" ConnectionTimeOut" , 30 , CONFIGURATION_FN , true , true , true , false );
3737 minimumStatusDuration = declareConfiguration<int >(" MinimumStatusDuration" , 0 , CONFIGURATION_FN , true , true , true , false );
38+ stopTransactionOnInvalidId = declareConfiguration<const char *>(" StopTransactionOnInvalidId" , " true" , CONFIGURATION_FN , true , true , false , false );
39+ stopTransactionOnEVSideDisconnect = declareConfiguration<const char *>(" StopTransactionOnEVSideDisconnect" , " true" , CONFIGURATION_FN , true , true , false , false );
3840
3941 if (!sIdTag || !transactionId || !availability) {
4042 AO_DBG_ERR (" Cannot declare sessionIdTag, transactionId or availability" );
@@ -89,12 +91,13 @@ OcppEvseState ConnectorStatus::inferenceStatus() {
8991 return OcppEvseState::Preparing;
9092 } else {
9193 // Transaction is currently running
94+ if ((connectorEnergizedSampler && !connectorEnergizedSampler ()) ||
95+ idTagInvalidated) {
96+ return OcppEvseState::SuspendedEVSE;
97+ }
9298 if (evRequestsEnergySampler && !evRequestsEnergySampler ()) {
9399 return OcppEvseState::SuspendedEV;
94100 }
95- if (connectorEnergizedSampler && !connectorEnergizedSampler ()) {
96- return OcppEvseState::SuspendedEVSE;
97- }
98101 return OcppEvseState::Charging;
99102 }
100103}
@@ -105,6 +108,10 @@ bool ConnectorStatus::ocppPermitsCharge() {
105108 return false ;
106109 }
107110
111+ if (idTagInvalidated) {
112+ return false ;
113+ }
114+
108115 OcppEvseState state = inferenceStatus ();
109116
110117 return state == OcppEvseState::Charging ||
@@ -117,19 +124,26 @@ OcppMessage *ConnectorStatus::loop() {
117124 *availability = AVAILABILITY_INOPERATIVE ;
118125 saveState ();
119126 }
127+
128+ if (connectorPluggedSampler) {
129+ if (getTransactionId () >= 0 && !connectorPluggedSampler ()) {
130+ if (!*stopTransactionOnEVSideDisconnect || strcmp (*stopTransactionOnEVSideDisconnect, " false" )) {
131+ endSession (" EVDisconnected" );
132+ }
133+ }
134+ }
120135
121136 /*
122137 * Check conditions for start or stop transaction
123138 */
124139 if (connectorPluggedSampler) { // only supported with connectorPluggedSampler
125140 if (getTransactionId () >= 0 ) {
126141 // check condition for StopTransaction
127- if (!connectorPluggedSampler () ||
128- !session) {
142+ if (!session) {
129143 AO_DBG_DEBUG (" Session mngt: txId=%i, connectorPlugged=%d, session=%d" ,
130144 getTransactionId (), connectorPluggedSampler (), session);
131145 AO_DBG_INFO (" Session mngt: trigger StopTransaction" );
132- return new StopTransaction (connectorId);
146+ return new StopTransaction (connectorId, endReason[ 0 ] != ' \0 ' ? endReason : nullptr );
133147 }
134148 } else {
135149 // check condition for StartTransaction
@@ -163,7 +177,7 @@ OcppMessage *ConnectorStatus::loop() {
163177 if (inferencedStatus != currentStatus) {
164178 currentStatus = inferencedStatus;
165179 t_statusTransition = ao_tick_ms ();
166- AO_DBG_DEBUG (" Status changed%s" , *minimumStatusDuration > 0 ? " , will report delayed" , " " );
180+ AO_DBG_DEBUG (" Status changed%s" , *minimumStatusDuration ? " , will report delayed" : " " );
167181 }
168182
169183 if (reportedStatus != currentStatus &&
@@ -200,23 +214,43 @@ void ConnectorStatus::beginSession(const char *sessionIdTag) {
200214 sIdTag ->setValue (idTag, IDTAG_LEN_MAX + 1 );
201215 saveState ();
202216 session = true ;
217+ idTagInvalidated = false ;
218+
219+ memset (endReason, ' \0 ' , REASON_LEN_MAX + 1 );
203220
204221 connectionTimeOutListen = true ;
205222 connectionTimeOutTimestamp = ao_tick_ms ();
206223}
207224
208- void ConnectorStatus::endSession () {
209- AO_DBG_DEBUG (" End session with idTag %s" , idTag);
225+ void ConnectorStatus::endSession (const char *reason) {
226+ AO_DBG_DEBUG (" End session with idTag %s for reason %s, %s previous reason" ,
227+ idTag, reason ? reason : " undefined" ,
228+ endReason[0 ] == ' \0 ' ? " no" : " overruled by" );
210229 if (session) {
211230 memset (idTag, ' \0 ' , IDTAG_LEN_MAX + 1 );
212231 *sIdTag = " " ;
213232 saveState ();
214233 }
215234 session = false ;
216235
236+ if (reason && endReason[0 ] == ' \0 ' ) {
237+ snprintf (endReason, REASON_LEN_MAX + 1 , " %s" , reason);
238+ }
239+
217240 connectionTimeOutListen = false ;
218241}
219242
243+ void ConnectorStatus::setIdTagInvalidated () {
244+ if (session) {
245+ idTagInvalidated = true ;
246+ if (!*stopTransactionOnInvalidId || strcmp (*stopTransactionOnInvalidId, " false" )) {
247+ endSession (" DeAuthorized" );
248+ }
249+ } else {
250+ AO_DBG_WARN (" Cannot invalidate IdTag outside of session" );
251+ }
252+ }
253+
220254const char *ConnectorStatus::getSessionIdTag () {
221255 return session ? idTag : nullptr ;
222256}
0 commit comments