Skip to content

Commit

Permalink
Merge pull request #960 from frogonwheels/poller-factor-poll-list
Browse files Browse the repository at this point in the history
OBD Poller - Cleaner interface to Poll-List and retrieving next entry
  • Loading branch information
dexterbg committed Jan 15, 2024
2 parents 7125741 + 07e628e commit 88f5ec5
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 74 deletions.
15 changes: 13 additions & 2 deletions vehicle/OVMS.V3/components/vehicle/vehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,17 @@ const char* OvmsVehicle::VehicleType()
return MyVehicleFactory.ActiveVehicleType();
}

const char *OvmsVehicle::PollerSource(OvmsVehicle::poller_source_t src)
{
switch (src)
{
case poller_source_t::Primary: return "PRI";
case poller_source_t::Successful: return "SRX";
case poller_source_t::OnceOff: return "ONE";
}
return "XXX";
}

void OvmsVehicle::RxTask()
{
CAN_frame_t frame;
Expand All @@ -478,7 +489,7 @@ void OvmsVehicle::RxTask()
{
PollerVWTPReceive(&frame, frame.MsgID);
}
else if (m_poll_wait && frame.origin == m_poll.bus && m_poll_plist)
else if (m_poll_wait && frame.origin == m_poll.bus && HasPollList())
{
uint32_t msgid;
if (m_poll.protocol == ISOTP_EXTADR)
Expand Down Expand Up @@ -572,7 +583,7 @@ void OvmsVehicle::VehicleTicker1(std::string event, void* data)
m_ticker++;

PollerStateTicker();
PollerSend(true);
PollerSend(poller_source_t::Primary);

Ticker1(m_ticker);
if ((m_ticker % 10) == 0) Ticker10(m_ticker);
Expand Down
28 changes: 26 additions & 2 deletions vehicle/OVMS.V3/components/vehicle/vehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,9 +357,15 @@ class OvmsVehicle : public InternalRamAllocated
private:
void VehicleTicker1(std::string event, void* data);
void VehicleConfigChanged(std::string event, void* data);
void PollerSend(bool fromTicker);
void PollerResetThrottle();

typedef enum { Primary, Successful, OnceOff } poller_source_t;
void PollerSend(poller_source_t source);
static const char *PollerSource(OvmsVehicle::poller_source_t src);

protected:
virtual void PollRunFinished();

virtual void IncomingFrameCan1(CAN_frame_t* p_frame);
virtual void IncomingFrameCan2(CAN_frame_t* p_frame);
virtual void IncomingFrameCan3(CAN_frame_t* p_frame);
Expand Down Expand Up @@ -583,13 +589,20 @@ class OvmsVehicle : public InternalRamAllocated
virtual bool SetFeature(int key, const char* value);
virtual const std::string GetFeature(int key);

enum class OvmsNextPollResult
{
StillAtEnd,
FoundEntry,
ReachedEnd
};

protected:
OvmsRecMutex m_poll_mutex; // Concurrency protection for recursive calls
uint8_t m_poll_state; // Current poll state
canbus* m_poll_bus_default; // Bus default to poll on
const OvmsPoller::poll_pid_t* m_poll_plist; // Head of poll list
const OvmsPoller::poll_pid_t* m_poll_plcur; // Poll list loop cursor
private:
const OvmsPoller::poll_pid_t* m_poll_plcur; // Poll list loop cursor
// Poll state for received data.
OvmsPoller::poll_job_t m_poll;

Expand All @@ -607,7 +620,18 @@ class OvmsVehicle : public InternalRamAllocated
// Only when the reply doesn't get in until the next ticker occurs
// PollserSend() decrements to 0 and abandons the outstanding reply (=timeout)


protected:
// Poll entry manipulation: Must be called under lock of m_poll_mutex
void ResetPollEntry();
bool HasPollList();

OvmsNextPollResult NextPollEntry(OvmsPoller::poll_pid_t *entry);
void PollerNextTick(poller_source_t source);

// Check for throttling.
bool CanPoll();

// Polling Response
virtual void IncomingPollReply(const OvmsPoller::poll_job_t &job, uint8_t* data, uint8_t length);
virtual void IncomingPollError(const OvmsPoller::poll_job_t &job, uint16_t code);
Expand Down
155 changes: 119 additions & 36 deletions vehicle/OVMS.V3/components/vehicle/vehicle_poller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
*/

// #include "ovms_log.h"
// static const char *TAG = "vehicle";
static const char *TAG = "vehicle-poll";

#include <stdio.h>
#include <algorithm>
Expand Down Expand Up @@ -128,9 +128,7 @@ void OvmsVehicle::PollSetPidList(canbus* bus, const OvmsPoller::poll_pid_t* plis
m_poll.ticker = 0;
m_poll_sequence_cnt = 0;
m_poll_wait = 0;
m_poll_plcur = NULL;
m_poll.entry = {};
m_poll_txmsgid = 0;
ResetPollEntry();
}


Expand Down Expand Up @@ -217,22 +215,112 @@ void OvmsVehicle::PollSetChannelKeepalive(uint16_t keepalive_seconds)
m_poll_ch_keepalive = keepalive_seconds;
}

void OvmsVehicle::PollerResetThrottle()
{
// Main Timer reset throttling counter,
m_poll_sequence_cnt = 0;
}

void OvmsVehicle::ResetPollEntry()
{
m_poll_plcur = NULL;
m_poll.entry = {};
m_poll_txmsgid = 0;
}

bool OvmsVehicle::HasPollList()
{
return (m_poll_bus_default != NULL)
&& (m_poll_plist != NULL)
&& (m_poll_plist->txmoduleid != 0);
}

bool OvmsVehicle::CanPoll()
{
// Check Throttle
return (!m_poll_sequence_max || m_poll_sequence_cnt < m_poll_sequence_max);
}

OvmsVehicle::OvmsNextPollResult OvmsVehicle::NextPollEntry(OvmsPoller::poll_pid_t *entry)
{
*entry = {};
// Restart poll list cursor:
if (m_poll_plcur == NULL)
m_poll_plcur = m_poll_plist;
else if (m_poll_plcur->txmoduleid == 0)
return OvmsNextPollResult::StillAtEnd;
else
++m_poll_plcur;

while (m_poll_plcur->txmoduleid != 0)
{
if ((m_poll_plcur->polltime[m_poll_state] > 0) &&
((m_poll.ticker % m_poll_plcur->polltime[m_poll_state]) == 0))
{
*entry = *m_poll_plcur;
return OvmsNextPollResult::FoundEntry;
}
// Poll entry is not due, check next
++m_poll_plcur;
}
return OvmsNextPollResult::ReachedEnd;
}

void OvmsVehicle::PollerNextTick(poller_source_t source)
{
// Completed checking all poll entries for the current m_poll_ticker
ESP_LOGD(TAG, "PollerSend(%s): cycle complete for ticker=%u", PollerSource(source), m_poll.ticker);

// Allow POLL to restart.
m_poll_plcur = NULL;

m_poll.ticker++;
if (m_poll.ticker > 3600) m_poll.ticker -= 3600;
}

/** Called after reaching the end of available POLL entries.
*/
void OvmsVehicle::PollRunFinished()
{
}

/**
* PollerSend: internal: start next due request
*/
void OvmsVehicle::PollerSend(bool fromTicker)
void OvmsVehicle::PollerSend(poller_source_t source)
{
OvmsRecMutexLock lock(&m_poll_mutex);

// ESP_LOGD(TAG, "PollerSend(%d): entry at[type=%02X, pid=%X], ticker=%u, wait=%u, cnt=%u/%u",
// fromTicker, m_poll_plcur->type, m_poll_plcur->pid,
// m_poll_ticker, m_poll_wait, m_poll_sequence_cnt, m_poll_sequence_max);

if (fromTicker)
bool fromPrimaryTicker = false, fromOnceOffTicker = false;
switch (source)
{
// Timer ticker call: reset throttling counter, check response timeout
m_poll_sequence_cnt = 0;
case poller_source_t::OnceOff:
fromOnceOffTicker = true;
break;
case poller_source_t::Primary:
fromPrimaryTicker = true;
break;
default:
;
}
if (fromPrimaryTicker)
{
// Timer ticker call: reset throttling counter
PollerResetThrottle();

// Only reset the list when 'from Ticker' and it's at the end.
if (m_poll_plcur && m_poll_plcur->txmoduleid == 0)
{
PollerNextTick(source);
}
}
if (fromPrimaryTicker || fromOnceOffTicker)
{
// Timer ticker call: check response timeout
if (m_poll_wait > 0) m_poll_wait--;

// Protocol specific ticker calls:
Expand All @@ -241,25 +329,30 @@ void OvmsVehicle::PollerSend(bool fromTicker)
if (m_poll_wait > 0) return;

// Check poll bus & list:
if (!m_poll_bus_default || !m_poll_plist || m_poll_plist->txmoduleid == 0) return;

// Restart poll list cursor:
if (m_poll_plcur == NULL) m_poll_plcur = m_poll_plist;
if (!HasPollList()) return;

m_poll.entry = {};

while (m_poll_plcur->txmoduleid != 0)
switch (NextPollEntry(&m_poll.entry))
{
if ((m_poll_plcur->polltime[m_poll_state] > 0) &&
((m_poll.ticker % m_poll_plcur->polltime[m_poll_state]) == 0))
case OvmsNextPollResult::ReachedEnd:
PollRunFinished();
// fall through
case OvmsNextPollResult::StillAtEnd:
{
PollerNextTick(source);
break;
}
case OvmsNextPollResult::FoundEntry:
{
ESP_LOGD(TAG, "PollerSend(%s)[%d]: entry at[type=%02X, pid=%X], ticker=%u, wait=%u, cnt=%u/%u",
PollerSource(source), m_poll_state, m_poll.entry.type, m_poll.entry.pid,
m_poll.ticker, m_poll_wait, m_poll_sequence_cnt, m_poll_sequence_max);
// We need to poll this one...
m_poll.entry = *m_poll_plcur;
m_poll.protocol = m_poll_plcur->protocol;
m_poll.type = m_poll_plcur->type;
m_poll.pid = m_poll_plcur->pid;
m_poll.protocol = m_poll.entry.protocol;
m_poll.type = m_poll.entry.type;
m_poll.pid = m_poll.entry.pid;

switch (m_poll_plcur->pollbus)
switch (m_poll.entry.pollbus)
{
case 1:
m_poll.bus = m_can1;
Expand All @@ -279,24 +372,14 @@ void OvmsVehicle::PollerSend(bool fromTicker)

// Dispatch transmission start to protocol handler:
if (m_poll.protocol == VWTP_20)
PollerVWTPStart(fromTicker);
PollerVWTPStart(fromPrimaryTicker);
else
PollerISOTPStart(fromTicker);
PollerISOTPStart(fromPrimaryTicker);

m_poll_plcur++;
m_poll_sequence_cnt++;
return;
break;
}

// Poll entry is not due, check next
m_poll_plcur++;
}

// Completed checking all poll entries for the current m_poll.ticker
// ESP_LOGD(TAG, "PollerSend(%d): cycle complete for ticker=%u", fromTicker, m_poll.ticker);
m_poll_plcur = m_poll_plist;
m_poll.ticker++;
if (m_poll.ticker > 3600) m_poll.ticker -= 3600;
}


Expand All @@ -308,7 +391,7 @@ void OvmsVehicle::PollerTxCallback(const CAN_frame_t* frame, bool success)
OvmsRecMutexLock lock(&m_poll_mutex);

// Check for a late callback:
if (!m_poll_wait || !m_poll_plist || frame->origin != m_poll.bus || frame->MsgID != m_poll_txmsgid)
if (!m_poll_wait || !HasPollList() || frame->origin != m_poll.bus || frame->MsgID != m_poll_txmsgid)
return;

// Forward to protocol handler:
Expand Down Expand Up @@ -421,7 +504,7 @@ int OvmsVehicle::PollSingleRequest(canbus* bus, uint32_t txid, uint32_t rxid,
PollSetPidList(bus, poll);
m_poll_single_rxdone.Take(0);
m_poll_single_rxbuf = &response;
PollerSend(true);
PollerSend(poller_source_t::OnceOff);
m_poll_mutex.Unlock();

// wait for response:
Expand Down

0 comments on commit 88f5ec5

Please sign in to comment.