Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collection message #124

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
11 changes: 10 additions & 1 deletion gateway_to_backend/protocol_buffers_files/generic_message.proto
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,13 @@ message CustomerMessage {
message GenericMessage {
optional WirepasMessage wirepas = 1;
optional CustomerMessage customer = 2;
}
}

// This Generic Message collection allows a gateway, or a backend
// to group multiple message together to be transmitted as single mqtt
// message.
// It can only happen on collection topics to avoid mismatch with single
// message topic
message GenericMessageCollection {
repeated GenericMessage generic = 1;
}
44 changes: 44 additions & 0 deletions wrappers/python/tests/gateway/test_generic_collection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# flake8: noqa

from wirepas_messaging.gateway.api import *
from default_value import *


def test_generate_parse_collection():

event1 = ReceivedDataEvent(
GATEWAY_ID,
SINK_ID,
RX_TIME_MS_EPOCH,
SOURCE_ADD,
DESTINATION_ADD,
SOURCE_EP,
DESTINATION_EP,
TRAVEL_TIME_MS,
QOS,
DATA_PAYLOAD,
hop_count=HOP_COUNT,
)

event2 = ReceivedDataEvent(
GATEWAY_ID,
SINK_ID,
RX_TIME_MS_EPOCH + 10,
SOURCE_ADD,
DESTINATION_ADD,
SOURCE_EP,
DESTINATION_EP,
TRAVEL_TIME_MS,
QOS,
DATA_PAYLOAD,
hop_count=HOP_COUNT,
)

message_list = [event1, event2]

collection = GenericCollection(message_list)

collection2 = GenericCollection.from_payload(collection.payload)

for message in collection2.messages:
assert isinstance(message, ReceivedDataEvent)
1 change: 1 addition & 0 deletions wrappers/python/wirepas_messaging/gateway/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@
from .gateway_result_code import *
from .otap_helper import *
from .wirepas_exceptions import *
from .generic_collection import *
12 changes: 3 additions & 9 deletions wrappers/python/wirepas_messaging/gateway/api/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
import random
import wirepas_messaging

from .generic_message import GenericMessage

class Event(object):

class Event(GenericMessage):
"""
Event

Expand All @@ -30,14 +32,6 @@ def __init__(self, gw_id, sink_id=None, event_id=None, **kwargs):
event_id = random.getrandbits(64)
self.event_id = event_id

def __str__(self):
return str(self.__dict__)

@property
def payload(self):
""" Implement how to serialize child Event classes """
raise NotImplementedError()

def _make_event_header(self):
""" Creates the generic messaging header """
header = wirepas_messaging.gateway.EventHeader()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""
Generic collection
=============

.. Copyright:
Copyright 2020 Wirepas Ltd under Apache License, Version 2.0.
See file LICENSE for full license details.
"""
# flake8: noqa
from wirepas_messaging.gateway.api import *


class GenericCollection(object):
"""
GenericCollection: collection of Generic message

"""

field_to_class = {
"status_event": StatusEvent,
"get_configs_req": GetConfigsRequest,
"get_configs_resp": GetConfigsResponse,
"set_config_req": SetConfigRequest,
"set_config_resp": SetConfigResponse,
"send_packet_req": SendDataRequest,
"send_packet_resp": SendDataResponse,
"packet_received_event": ReceivedDataEvent,
"get_scratchpad_status_req": GetScratchpadStatusRequest,
"get_scratchpad_status_resp": GetScratchpadStatusResponse,
"upload_scratchpad_req": UploadScratchpadRequest,
"upload_scratchpad_resp": UploadScratchpadResponse,
"process_scratchpad_req": ProcessScratchpadRequest,
"process_scratchpad_resp": ProcessScratchpadResponse,
"get_gateway_info_req": GetGatewayInfoRequest,
"get_gateway_info_res": GetGatewayInfoResponse,
}

def __init__(self, generic_messages_list, **kwargs):
self.generic_messages_list = generic_messages_list

@classmethod
def from_payload(cls, payload):
message_collection = wirepas_messaging.gateway.GenericMessageCollection()
try:
message_collection.ParseFromString(payload)
except Exception:
# Any Exception is promoted to Generic API exception
raise GatewayAPIParsingException("Cannot parse Generic payload collection")

msgs_list = []
for message in message_collection.generic:
for field, class_holder in GenericCollection.field_to_class.items():
if message.wirepas.HasField(field):
msgs_list.append(class_holder.from_generic_message(message))
break

return cls(msgs_list)

@property
def payload(self):
message_collection = wirepas_messaging.gateway.GenericMessageCollection()
# Add all messages one by one
for message in self.generic_messages_list:
message_collection.generic.append(message.generic_message)

return message_collection.SerializeToString()

@property
def messages(self):
return self.generic_messages_list

def add_message(self, message):
self.generic_messages_list.append(message)
51 changes: 51 additions & 0 deletions wrappers/python/wirepas_messaging/gateway/api/generic_message.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""
Generic message
========

.. Copyright:
Copyright 2020 Wirepas Ltd under Apache License, Version 2.0.
See file LICENSE for full license details.
"""

import wirepas_messaging

from .wirepas_exceptions import GatewayAPIParsingException


class GenericMessage(object):
"""
Generic message

Base class for all Events, Requests, Response

"""

@classmethod
def from_generic_message(cls, message):
""" Implement how to parse message """
raise NotImplementedError()

@classmethod
def from_payload(cls, payload):
message = wirepas_messaging.gateway.GenericMessage()
try:
message.ParseFromString(payload)
except Exception:
# Any Exception is promoted to Generic API exception
raise GatewayAPIParsingException(
"Cannot parse payload for %s" % cls.__name__
)

return cls.from_generic_message(message)

@property
def generic_message(self):
""" Implement how to generate generic message"""
raise NotImplementedError()

@property
def payload(self):
return self.generic_message.SerializeToString()

def __str__(self):
return str(self.__dict__)
27 changes: 6 additions & 21 deletions wrappers/python/wirepas_messaging/gateway/api/get_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
set_config_ro,
set_config_rw,
)
from .wirepas_exceptions import GatewayAPIParsingException


class GetConfigsRequest(Request):
Expand All @@ -33,25 +32,18 @@ def __init__(self, req_id=None, **kwargs):
super(GetConfigsRequest, self).__init__(req_id=req_id, **kwargs)

@classmethod
def from_payload(cls, payload):
message = wirepas_messaging.gateway.GenericMessage()
try:
message.ParseFromString(payload)
except Exception:
# Any Exception is promoted to Generic API exception
raise GatewayAPIParsingException("Cannot parse GetConfigsRequest payload")

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

@property
def payload(self):
def generic_message(self):
message = wirepas_messaging.gateway.GenericMessage()
# Fill the request header
get_config = message.wirepas.get_configs_req
get_config.header.CopyFrom(self._make_request_header())

return message.SerializeToString()
return message


class GetConfigsResponse(Response):
Expand All @@ -70,14 +62,7 @@ def __init__(self, req_id, gw_id, res, configs, **kwargs):
self.configs = configs

@classmethod
def from_payload(cls, payload):
message = wirepas_messaging.gateway.GenericMessage()
try:
message.ParseFromString(payload)
except Exception:
# Any Exception is promoted to Generic API exception
raise GatewayAPIParsingException("Cannot parse GetConfigsResponse payload")

def from_generic_message(cls, message):
response = message.wirepas.get_configs_resp

d = Response._parse_response_header(response.header)
Expand All @@ -97,7 +82,7 @@ def from_payload(cls, payload):
return cls(d["req_id"], d["gw_id"], d["res"], configs)

@property
def payload(self):
def generic_message(self):
message = wirepas_messaging.gateway.GenericMessage()

response = message.wirepas.get_configs_resp
Expand All @@ -110,4 +95,4 @@ def payload(self):
set_config_rw(conf, config)
set_config_ro(conf, config)

return message.SerializeToString()
return message
32 changes: 6 additions & 26 deletions wrappers/python/wirepas_messaging/gateway/api/get_gw_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
from .request import Request
from .response import Response

from .wirepas_exceptions import GatewayAPIParsingException


class GetGatewayInfoRequest(Request):
"""
Expand All @@ -27,27 +25,18 @@ def __init__(self, req_id=None, **kwargs):
super(GetGatewayInfoRequest, self).__init__(req_id=req_id, **kwargs)

@classmethod
def from_payload(cls, payload):
message = wirepas_messaging.gateway.GenericMessage()
try:
message.ParseFromString(payload)
except Exception:
# Any Exception is promoted to Generic API exception
raise GatewayAPIParsingException(
"Cannot parse GetGatewayInfoRequest payload"
)

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

@property
def payload(self):
def generic_message(self):
message = wirepas_messaging.gateway.GenericMessage()
# Fill the request header
get_gateway_info = message.wirepas.get_gateway_info_req
get_gateway_info.header.CopyFrom(self._make_request_header())

return message.SerializeToString()
return message


class GetGatewayInfoResponse(Response):
Expand Down Expand Up @@ -81,16 +70,7 @@ def __init__(
self.implemented_api_version = implemented_api_version

@classmethod
def from_payload(cls, payload):
message = wirepas_messaging.gateway.GenericMessage()
try:
message.ParseFromString(payload)
except Exception:
# Any Exception is promoted to Generic API exception
raise GatewayAPIParsingException(
"Cannot parse GetGatewayInfoResponse payload"
)

def from_generic_message(cls, message):
response = message.wirepas.get_gateway_info_resp

d = Response._parse_response_header(response.header)
Expand All @@ -106,7 +86,7 @@ def from_payload(cls, payload):
)

@property
def payload(self):
def generic_message(self):
message = wirepas_messaging.gateway.GenericMessage()

response = message.wirepas.get_gateway_info_resp
Expand All @@ -123,4 +103,4 @@ def payload(self):
if self.implemented_api_version is not None:
response.info.implemented_api_version = self.implemented_api_version

return message.SerializeToString()
return message
Loading