Skip to content

Commit

Permalink
Message process retry after unexpected message arrival (#13)
Browse files Browse the repository at this point in the history
* raised errors to prevent ongoing of the match sequence and hanlded ir properly in the upper layers

* bumped the atten results timeout to 1150 ms as Alfen board takes more time now to forward the frames as they have the traffic encripted

* added TimeoutError to the error handling

* fix install-local

* fixed handling error setting the nmid and nmk

* refactored the code and tests to remain in the same states until the correct frame is received or a timeour is raised

* reformated code

* moved the homeplug frame check before the parsing of the bytes to the class
  • Loading branch information
tropxy authored Apr 12, 2022
1 parent 267b662 commit 53fe509
Show file tree
Hide file tree
Showing 7 changed files with 435 additions and 431 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ poetry-update: poetry-config
poetry update

install-local: .check-env-vars
pip install . --extra-index-url https://$PYPI_USER:$PYPI_PASS@pypi.switch-ev.com/simple
pip install . --extra-index-url https://${PYPI_USER}:${PYPI_PASS}@pypi.switch-ev.com/simple

run-local:
python slac/main.py
Expand Down
401 changes: 185 additions & 216 deletions poetry.lock

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ authors = ["André Duarte <andre@switch-ev.com, andre14x@gmail.com>"]

[tool.poetry.dependencies]
python = "^3.9"
environs = "^9.3.5"
environs = "^9.5.0"
mqtt-api = { version = "^0.18.1", source = "pypi-switch"}

[tool.poetry.dev-dependencies]
pytest = "^6.2.5"
pytest = "^7.1.1"
pytest-lazy-fixture = "^0.6.3"
pytest-cov = "^3.0.0"
pytest-pylint = "^0.18.0"
pytest-watch = "^4.2.0"
pytest-asyncio = "^0.16.0"
black = "21.11b1"
pytest-asyncio = "^0.18.3"
black = "22.3.0"
isort = "^5.10.1"
flake8 = "^4.0.1"

Expand Down
2 changes: 1 addition & 1 deletion slac/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class Timers(float, Enum):
# Timers.SLAC_ATTEN_TIMEOUT is the only value in the Timers class that its use
# is supposed to be done as an integer (type int)
SLAC_ATTEN_TIMEOUT = 6 # [TT_EVSE_match_MNBC = 600 ms]
ATTEN_RESULTS_TIMEOUT = 9 # in ms
ATTEN_RESULTS_TIMEOUT = 1150 # in ms


class FramesSizes(int, Enum):
Expand Down
63 changes: 46 additions & 17 deletions slac/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@

@dataclass
class SlacStatusPayload:
"""
Dataclass to hold the SlacStatus Payload info
This class is here as it was missing from mqtt_api by the time this code
was implemented.
"""

evse_id: str
status: SlacStatus

Expand Down Expand Up @@ -82,29 +88,44 @@ async def get_cs_parameters(self):
"network_interface": "eth0",
"connectors": [...],
If no answer is provided in 60s, a timeout occurs and the slac application stops
If no answer is provided in 60s, a timeout occurs and the slac application
stops. If the Initialization of the Slac session based on the CS Parameters
received fails, the system restarts awaiting for the parameters after 5 secs.
Note:
The evse_id provided must be unique and is assumed to be associated to
one and one only network_interface. This is important, as the 'evse_id' is
used in subsequent messages as an identifier of the running session.
"""
cs_parameters: response.CsParametersPayload = await self.request(
topic=Topics.JOSEV_CS, payload=request.CsParametersPayload()
)
while not self.running_sessions:
cs_parameters: response.CsParametersPayload = await self.request(
topic=Topics.JOSEV_CS, payload=request.CsParametersPayload()
)

if cs_parameters.number_of_evses < 1 or (
len(cs_parameters.parameters) != cs_parameters.number_of_evses
):
raise AttributeError("Number of evses provided is invalid.")
if cs_parameters.number_of_evses < 1 or (
len(cs_parameters.parameters) != cs_parameters.number_of_evses
):
raise AttributeError("Number of evses provided is invalid.")

for evse_params in cs_parameters.parameters:
# Initialize the Slac Session
slac_session = SlacEvseSession(
evse_params.evse_id, evse_params.network_interface, self.config
)
await slac_session.evse_set_key()
self.running_sessions.append(slac_session)
for evse_params in cs_parameters.parameters:
# Initialize the Slac Session
try:
slac_session = SlacEvseSession(
evse_params.evse_id, evse_params.network_interface, self.config
)
await slac_session.evse_set_key()
self.running_sessions.append(slac_session)
except (OSError, TimeoutError, ValueError) as e:
logger.error(
f"PLC chip initialization failed for "
f"EVSE {evse_params.evse_id}, interface "
f"{evse_params.network_interface}: {e}. \n"
f"Please check your CS parameters. The CS Parameters"
f"request will be resent in 5 secs"
)
self.running_sessions.clear()
await asyncio.sleep(5)
break

@get_session
@on(MessageName.CP_STATUS)
Expand Down Expand Up @@ -146,7 +167,7 @@ async def matching_process(
self, slac_session: "SlacEvseSession", number_of_retries=3
) -> None:
"""
Task that is spawned once a state change is detected from A. E or F to
Task that is spawned once a state change is detected from A, E or F to
B, C or D. This task is responsible to run the right methods defined in
session.py, which as a whole comprise the SLAC protocol.
In case SLAC fails, it retries up to 3 times to get a match, and
Expand All @@ -169,7 +190,15 @@ async def matching_process(
slac_session.evse_id, SlacStatus.MATCHING
),
)
await slac_session.atten_charac_routine()
try:
await slac_session.atten_charac_routine()
except Exception as e:
slac_session.state = STATE_UNMATCHED
logger.debug(
f"Exception Occurred during Attenuation Charc Routine:"
f"{e} \n"
f"Number of retries left {number_of_retries}"
)
if slac_session.state == STATE_MATCHED:
logger.debug("PEV-EVSE MATCHED Successfully, Link Established")
while True:
Expand Down
Loading

0 comments on commit 53fe509

Please sign in to comment.