Skip to content

Commit

Permalink
Add support for timestamp in headers
Browse files Browse the repository at this point in the history
It uses the **kwargs argument we have for request/response/event
If time_ms_epoch is None => no timestamp in protobuf object
If time_ms_epoch is 0 => Automatically added in object creation (default)
If time_ms_epoch is set => Used as is
  • Loading branch information
GwendalRaoul committed Sep 7, 2022
1 parent 2109876 commit 5a83035
Show file tree
Hide file tree
Showing 16 changed files with 201 additions and 30 deletions.
2 changes: 1 addition & 1 deletion backend-apis
Submodule backend-apis updated 129 files
1 change: 1 addition & 0 deletions tests/test_get_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import wirepas_mesh_messaging
from default_value import *
import time

DUMMY_CONFIGS = [NODE_CONFIG_1]

Expand Down
122 changes: 122 additions & 0 deletions tests/test_timestamp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# flake8: noqa

import wirepas_mesh_messaging
from default_value import *
import time

now_ms = int(time.time() * 1000)

def test_automatic_timestamp_request():
request = wirepas_mesh_messaging.UploadScratchpadRequest(
SCRATCHPAD_SEQ, SINK_ID, REQUEST_ID
)

assert request.time_ms_epoch <= time.time() * 1000

request2 = wirepas_mesh_messaging.UploadScratchpadRequest.from_payload(
request.payload
)

for k, v in request.__dict__.items():
assert v == request2.__dict__[k]

def test_no_timestamp_request():
request = wirepas_mesh_messaging.UploadScratchpadRequest(
SCRATCHPAD_SEQ, SINK_ID, REQUEST_ID, time_ms_epoch=None
)

assert request.time_ms_epoch == None

request2 = wirepas_mesh_messaging.UploadScratchpadRequest.from_payload(
request.payload
)

for k, v in request.__dict__.items():
assert v == request2.__dict__[k]

def test_timestamp_request():
request = wirepas_mesh_messaging.UploadScratchpadRequest(
SCRATCHPAD_SEQ, SINK_ID, REQUEST_ID, time_ms_epoch = now_ms
)

assert request.time_ms_epoch == now_ms

request2 = wirepas_mesh_messaging.UploadScratchpadRequest.from_payload(
request.payload
)

for k, v in request.__dict__.items():
assert v == request2.__dict__[k]


def test_automatic_timestamp_response():
response = wirepas_mesh_messaging.UploadScratchpadResponse(
REQUEST_ID, GATEWAY_ID, RES_OK, SINK_ID
)

assert response.time_ms_epoch <= time.time() * 1000

response2 = wirepas_mesh_messaging.UploadScratchpadResponse.from_payload(
response.payload
)

for k, v in response.__dict__.items():
assert v == response2.__dict__[k]

def test_no_timestamp_response():
response = wirepas_mesh_messaging.UploadScratchpadResponse(
REQUEST_ID, GATEWAY_ID, RES_OK, SINK_ID, time_ms_epoch = None
)

assert response.time_ms_epoch == None

response2 = wirepas_mesh_messaging.UploadScratchpadResponse.from_payload(
response.payload
)

for k, v in response.__dict__.items():
assert v == response2.__dict__[k]

def test_timestamp_response():
response = wirepas_mesh_messaging.UploadScratchpadResponse(
REQUEST_ID, GATEWAY_ID, RES_OK, SINK_ID, time_ms_epoch = now_ms
)

assert response.time_ms_epoch == now_ms

response2 = wirepas_mesh_messaging.UploadScratchpadResponse.from_payload(
response.payload
)

for k, v in response.__dict__.items():
assert v == response2.__dict__[k]

def test_automatic_timestamp_event():
status = wirepas_mesh_messaging.StatusEvent(GATEWAY_ID, GATEWAY_STATE)

assert status.time_ms_epoch <= time.time() * 1000

status2 = wirepas_mesh_messaging.StatusEvent.from_payload(status.payload)

for k, v in status.__dict__.items():
assert v == status2.__dict__[k]

def test_no_timestamp_event():
status = wirepas_mesh_messaging.StatusEvent(GATEWAY_ID, GATEWAY_STATE, time_ms_epoch = None)

assert status.time_ms_epoch == None

status2 = wirepas_mesh_messaging.StatusEvent.from_payload(status.payload)

for k, v in status.__dict__.items():
assert v == status2.__dict__[k]

def test__timestamp_event():
status = wirepas_mesh_messaging.StatusEvent(GATEWAY_ID, GATEWAY_STATE, time_ms_epoch = now_ms)

assert status.time_ms_epoch == now_ms

status2 = wirepas_mesh_messaging.StatusEvent.from_payload(status.payload)

for k, v in status.__dict__.items():
assert v == status2.__dict__[k]
16 changes: 14 additions & 2 deletions wirepas_mesh_messaging/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
See file LICENSE for full license details.
"""
import random
from .proto import EventHeader
import time


class Event(object):
Expand All @@ -18,17 +18,21 @@ class Event(object):
gw_id (str): gateway unique identifier
sink_id(str): sink identifier
event_id(int): event unique id (random value generated if None)
time_ms_epoch(int): timestamp in ms of event generation (0 to automatically set it, the default)
"""

# pylint: disable=unused-argument
def __init__(self, gw_id, sink_id=None, event_id=None, **kwargs):
def __init__(self, gw_id, sink_id=None, event_id=None, time_ms_epoch=0, **kwargs):

super(Event, self).__init__()
self.gw_id = gw_id
self.sink_id = sink_id
if event_id is None:
event_id = random.getrandbits(64)
self.event_id = event_id
if time_ms_epoch == 0:
time_ms_epoch = int(time.time() * 1000)
self.time_ms_epoch = time_ms_epoch

def __str__(self):
return str(self.__dict__)
Expand All @@ -46,6 +50,9 @@ def _load_event_header(self, event):
if self.sink_id is not None:
header.sink_id = str(self.sink_id)

if self.time_ms_epoch is not None:
header.time_ms_epoch = self.time_ms_epoch

@staticmethod
def _parse_event_header(header):
"""
Expand All @@ -66,4 +73,9 @@ def _parse_event_header(header):
else:
d["sink_id"] = None

if header.HasField("time_ms_epoch"):
d["time_ms_epoch"] = header.time_ms_epoch
else:
d["time_ms_epoch"] = None

return d
5 changes: 3 additions & 2 deletions wirepas_mesh_messaging/get_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class GetConfigsRequest(Request):
Attributes:
req_id (int): unique request id
time_ms_epoch(int): timestamp in ms of request generation
"""

def __init__(self, req_id=None, **kwargs):
Expand All @@ -42,7 +43,7 @@ def from_payload(cls, payload):
raise GatewayAPIParsingException("Cannot parse GetConfigsRequest payload")

d = Request._parse_request_header(message.wirepas.get_configs_req.header)
return cls(d["req_id"])
return cls(d["req_id"], time_ms_epoch=d["time_ms_epoch"])

@property
def payload(self):
Expand Down Expand Up @@ -94,7 +95,7 @@ def from_payload(cls, payload):

configs.append(config)

return cls(d["req_id"], d["gw_id"], d["res"], configs)
return cls(d["req_id"], d["gw_id"], d["res"], configs, time_ms_epoch=d["time_ms_epoch"])

@property
def payload(self):
Expand Down
3 changes: 2 additions & 1 deletion wirepas_mesh_messaging/get_gw_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def from_payload(cls, payload):
)

d = Request._parse_request_header(message.wirepas.get_gateway_info_req.header)
return cls(d["req_id"])
return cls(d["req_id"], time_ms_epoch=d["time_ms_epoch"])

@property
def payload(self):
Expand Down Expand Up @@ -103,6 +103,7 @@ def from_payload(cls, payload):
gateway_model=response.info.gw_model,
gateway_version=response.info.gw_version,
implemented_api_version=response.info.implemented_api_version,
time_ms_epoch=d["time_ms_epoch"]
)

@property
Expand Down
3 changes: 2 additions & 1 deletion wirepas_mesh_messaging/get_scratchpad_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def from_payload(cls, payload):

d = Request._parse_request_header(req.header)

return cls(d["sink_id"], d["req_id"])
return cls(d["sink_id"], d["req_id"], time_ms_epoch=d["time_ms_epoch"])

@property
def payload(self):
Expand Down Expand Up @@ -154,6 +154,7 @@ def from_payload(cls, payload):
processed_scratchpad,
firmware_area_id,
target_scratchpad_and_action,
time_ms_epoch=d["time_ms_epoch"]
)

@property
Expand Down
4 changes: 2 additions & 2 deletions wirepas_mesh_messaging/process_scratchpad.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def from_payload(cls, payload):

d = Request._parse_request_header(req.header)

return cls(d["sink_id"], d["req_id"])
return cls(d["sink_id"], d["req_id"], time_ms_epoch=d["time_ms_epoch"])

@property
def payload(self):
Expand Down Expand Up @@ -84,7 +84,7 @@ def from_payload(cls, payload):

d = Response._parse_response_header(response.header)

return cls(d["req_id"], d["gw_id"], d["res"], d["sink_id"])
return cls(d["req_id"], d["gw_id"], d["res"], d["sink_id"], time_ms_epoch=d["time_ms_epoch"])

@property
def payload(self):
Expand Down
7 changes: 5 additions & 2 deletions wirepas_mesh_messaging/received_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ReceivedDataEvent(Event):
event_id(int): event unique id (random value generated if None)
hop_count(int): number of hop for the message to reach the gateway
network_address(int): network_address of this message
time_ms_epoch(int): timestamp in ms of event generation
"""

def __init__(
Expand All @@ -50,10 +51,11 @@ def __init__(
event_id=None,
hop_count=0,
network_address=None,
time_ms_epoch=None,
**kwargs
):
super(ReceivedDataEvent, self).__init__(
gw_id, sink_id, event_id=event_id, **kwargs
gw_id, sink_id, event_id=event_id, time_ms_epoch=time_ms_epoch, **kwargs
)
self.sink_id = sink_id
self.rx_time_ms_epoch = rx_time_ms_epoch
Expand Down Expand Up @@ -125,7 +127,8 @@ def from_payload(cls, payload):
data_size=payload_size,
event_id=d["event_id"],
hop_count=hop_count,
network_address=network_address
network_address=network_address,
time_ms_epoch=d["time_ms_epoch"]
)

@property
Expand Down
17 changes: 14 additions & 3 deletions wirepas_mesh_messaging/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
"""

import random
from .proto import RequestHeader

import time

class Request(object):
"""
Expand All @@ -18,15 +17,19 @@ class Request(object):
Attributes:
sink_id(str): sink identifier
req_id (int): identifier to help distinguish a response/request pair
time_ms_epoch(int): timestamp in ms of request generation (0 to automatically set it, the default)
"""

# pylint: disable=unused-argument
def __init__(self, sink_id=None, req_id=None, **kwargs):
def __init__(self, sink_id=None, req_id=None, time_ms_epoch=0, **kwargs):
super(Request, self).__init__()
self.sink_id = sink_id
if req_id is None:
req_id = random.getrandbits(64)
self.req_id = req_id
if time_ms_epoch == 0:
time_ms_epoch = int(time.time() * 1000)
self.time_ms_epoch = time_ms_epoch

def __str__(self):
return str(self.__dict__)
Expand All @@ -43,6 +46,9 @@ def _load_request_header(self, request):
if self.sink_id is not None:
header.sink_id = str(self.sink_id)

if self.time_ms_epoch is not None:
header.time_ms_epoch = self.time_ms_epoch

@staticmethod
def _parse_request_header(header):
"""
Expand All @@ -61,4 +67,9 @@ def _parse_request_header(header):
else:
d["sink_id"] = None

if header.HasField("time_ms_epoch"):
d["time_ms_epoch"] = header.time_ms_epoch
else:
d["time_ms_epoch"] = None

return d
16 changes: 14 additions & 2 deletions wirepas_mesh_messaging/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
See file LICENSE for full license details.
"""

from .proto import ResponseHeader
from .gateway_result_code import GatewayResultCode
import time


class Response(object):
Expand All @@ -20,15 +20,19 @@ class Response(object):
sink_id(str): sink identifier
req_id (int): identifier to help distinguish a response/request pair (same as in request)
res(GatewayResultCode): result of the operation
time_ms_epoch(int): timestamp in ms of response generation (0 to automatically set it, the default)
"""

# pylint: disable=unused-argument
def __init__(self, req_id, gw_id, res, sink_id=None, **kwargs):
def __init__(self, req_id, gw_id, res, sink_id=None, time_ms_epoch=0, **kwargs):
super(Response, self).__init__()
self.gw_id = gw_id
self.sink_id = sink_id
self.req_id = req_id
self.res = res
if time_ms_epoch == 0:
time_ms_epoch = int(time.time() * 1000)
self.time_ms_epoch = time_ms_epoch

def __str__(self):
return str(self.__dict__)
Expand All @@ -49,6 +53,9 @@ def _load_response_header(self, response):
if self.sink_id is not None:
header.sink_id = str(self.sink_id)

if self.time_ms_epoch is not None:
header.time_ms_epoch = self.time_ms_epoch

@staticmethod
def _parse_response_header(header):
"""
Expand All @@ -70,4 +77,9 @@ def _parse_response_header(header):
else:
d["sink_id"] = None

if header.HasField("time_ms_epoch"):
d["time_ms_epoch"] = header.time_ms_epoch
else:
d["time_ms_epoch"] = None

return d
Loading

0 comments on commit 5a83035

Please sign in to comment.