Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions wirepas_provisioning_server/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,62 @@
import cbor2
import yaml
import logging

from typing import Final, Optional
import dataclasses

from wirepas_provisioning_server.helpers import convert_to_bytes, convert_to_int, ProvisioningDataException
from wirepas_provisioning_server.message import ProvisioningMethod
from wirepas_provisioning_server.migrate_config import ConfigFileMigration


@dataclasses.dataclass(frozen=True)
class ProvisioningDataEndpoints:
"""Endpoints for provisioning data packets"""

req_ep: tuple[int, int]
resp_ep: tuple[int, int]


class ProvisioningDataConf:
"""Configuration class for provisioning data packets endpoints settings. Maps the networks
to profiles provisioning data packet endpoints."""

DATA_EPS: list[ProvisioningDataEndpoints] = [
ProvisioningDataEndpoints(req_ep=(246, 255), resp_ep=(255, 246)),
ProvisioningDataEndpoints(req_ep=(160, 39), resp_ep=(160, 40)),
]
PROFILE_EP_MAP: dict[str, ProvisioningDataEndpoints] # initialization made after class definition

def __init__(self, profiles: set[str] = set()) -> None:
self.data_endpoints: set[ProvisioningDataEndpoints] = set()
self.profiles: set[str] = set()
for profile in profiles:
self.add_profile(profile)

def add_profile(self, profile: str) -> None:
if profile in ProvisioningDataConf.PROFILE_EP_MAP.keys():
self.profiles.add(profile)
self.data_endpoints.add(ProvisioningDataConf.PROFILE_EP_MAP[profile])
else:
raise KeyError(
"Profile {} not not supported. Supported values are {}.".format(profile, self.PROFILE_EP_MAP.keys())
)

def get_resp_ep_by_req_ep(self, req_ep: tuple[int, int]) -> tuple[int, int]:
for data_ep in self.data_endpoints:
if req_ep == data_ep.req_ep:
return data_ep.resp_ep

raise KeyError("End point not found error: {}.".format(req_ep))


ProvisioningDataConf.PROFILE_EP_MAP = {
"2.4G": ProvisioningDataConf.DATA_EPS[0],
"SubG": ProvisioningDataConf.DATA_EPS[0],
"5GMesh": ProvisioningDataConf.DATA_EPS[1],
}


def _generate_extended_uid(
authenticator_uid_type_raw: str | int,
authenticator_uid_raw: str | int,
Expand Down Expand Up @@ -51,6 +99,8 @@ def __init__(self, config: Optional[str] = None):

super(ProvisioningData, self).__init__()

self.provisioning_data_conf = ProvisioningDataConf(profiles={"2.4G", "SubG", "5GMesh"})

if config is not None:
migration = ConfigFileMigration(config)
migration.update()
Expand Down Expand Up @@ -195,7 +245,7 @@ def append(
if factory_key is not None:
self[uid]["factory_key"] = factory_key

logging.info("Append new UID: %s", uid.hex())
logging.info("Append new UID#: %s", uid.hex())
logging.debug(" - method: %s", method)
logging.debug(" - factory_key: %s", factory_key)
logging.debug(" - encryption_key: %s", encryption_key)
Expand Down
11 changes: 8 additions & 3 deletions wirepas_provisioning_server/provisioning_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ def __init__(
self.sessions: dict[tuple[Optional[int], bytes, int], ProvisioningSession] = {}
self.data = ProvisioningData(settings)

# Register for packets on Provisioning Endpoints [246:255]
interface.register_data_cb(self.on_data_received, src_ep=246, dst_ep=255)
# Register for data packets to provisioning endpoints
for ep in self.data.provisioning_data_conf.data_endpoints:
interface.register_uplink_traffic_cb(self.on_data_received, src_ep=ep.req_ep[0], dst_ep=ep.req_ep[1])

def on_session_finish(self, key: tuple[int, bytes, int], status: ProvisioningStatus) -> None:
logging.info(
Expand All @@ -55,6 +56,7 @@ def on_session_finish(self, key: tuple[int, bytes, int], status: ProvisioningSta
def on_data_received(self, data: ReceivedDataEvent) -> None:
try:
msg_data = ProvisioningMessageFactory.map(data)
req_ep = (data.source_endpoint, data.destination_endpoint)
except ProvisioningMessageException as e:
print(e)
return
Expand All @@ -65,9 +67,12 @@ def on_data_received(self, data: ReceivedDataEvent) -> None:
self.sessions[msg_data.msg_id].event_q.put(ev)
logging.debug("Found SM with id: %s.", msg_data)
except KeyError:
logging.info("Create new SM with id: %s.", msg_data)
resp_ep = self.data.provisioning_data_conf.get_resp_ep_by_req_ep(req_ep)

logging.info("Create new SM with id: %s, ep:%d,%d.", msg_data, resp_ep[0], resp_ep[1])
self.sessions[msg_data.msg_id] = ProvisioningSession(
self.interface.send_message,
resp_ep,
msg_data.msg_id,
self.data,
self.on_session_finish,
Expand Down
13 changes: 12 additions & 1 deletion wirepas_provisioning_server/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class ProvisioningSession(threading.Thread):
def __init__(
self,
send_func: Callable,
resp_ep: tuple[int, int],
session_id: tuple[Optional[int], bytes, int],
data: ProvisioningData,
on_session_finish: Callable,
Expand All @@ -70,6 +71,7 @@ def __init__(
super(ProvisioningSession, self).__init__()

self.send_func = send_func
self.resp_ep = resp_ep
self.session_id = session_id
self.data = data
self.retry = retry
Expand Down Expand Up @@ -127,7 +129,13 @@ def _send_packet(self, payload: bytes) -> GatewayResultCode:
logging.debug(" - Sending packet (%s).", payload)
try:
return self.send_func(
gw_id=self.gw_id, sink_id=self.sink_id, dest=self.session_id[0], src_ep=255, dst_ep=246, qos=1, payload=payload
gw_id=self.gw_id,
sink_id=self.sink_id,
dest=self.session_id[0],
src_ep=self.resp_ep[0],
dst_ep=self.resp_ep[1],
qos=1,
payload=payload,
)
except TimeoutError:
logging.warning(" - Sending packet failed with timeout exception.")
Expand Down Expand Up @@ -205,6 +213,8 @@ def _process_start(self, msg: ProvisioningMessageSTART) -> None:
self.state = ProvisioningStates.WAIT_RESPONSE
self._timer_start(self.timeout)
break
else:
logging.debug(" - DATA packet not sent: res:{}.".format(res))

self.retry -= 1
if self.retry >= 0:
Expand All @@ -215,6 +225,7 @@ def _process_start(self, msg: ProvisioningMessageSTART) -> None:
logging.error(" - %s - Too many retry - Provisioning FAILURE.", msg)
self._timer_cancel()
self.status = ProvisioningStatus.ERROR_SENDING_DATA
return

else:
self.status = ProvisioningStatus.ERROR_NOT_AUTHORIZED
Expand Down