Skip to content

Commit 41b59d6

Browse files
committed
Added Metrics documentation and example in the readme
1 parent 44a65ca commit 41b59d6

2 files changed

Lines changed: 123 additions & 2 deletions

File tree

README.md

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,18 @@ This open-source project was sponsored by:
2121

2222
## Table of Contents
2323

24+
- [Key Features](#key-features)
2425
- [Installing the library](#installing-the-library)
25-
- [Getting Started - Generating Tokens](#getting-started---generating-tokens)
26-
- [Getting Started - Decoding a Token](#getting-started---decoding-a-token)
26+
- [Getting Started - OpenPAYGO Token](#getting-started---openpaygo-token)
27+
- [Generating Tokens](#generating-tokens)
28+
- [Decoding Tokens](#decoding-tokens)
29+
- [Getting Started - OpenPAYGO Metrics](#getting-started---openpaygo-metrics)
30+
- [Changelog](#changelog)
31+
- [2023-10-03 - v0.2.0](#2023-10-03---v020)
2732

33+
## Key Features
34+
- Implements token generation and decoding with full support for the v2.3 of the [OpenPAYGO Token](https://github.com/EnAccess/OpenPAYGO-Token) specifications.
35+
- Implements payload authentication (verification + signing) and conversion from simple to condensed payload (and back) with full support of the v1.0-rc1 of the [OpenPAYGO Metrics](https://github.com/openpaygo/metrics) specifications.
2836

2937
## Installing the library
3038

@@ -149,6 +157,70 @@ elif token_type == TokenType.INVALID:
149157
```
150158

151159

160+
## Getting Started - OpenPAYGO Metrics
161+
162+
163+
You can use the `MetricsHandler` object to process your OpenPAYGO Metrics request from start to finish. It accepts the following initial inputs:
164+
- `metrics_payload` (required): The OpenPAYGO Metrics payload, in a JSON string format.
165+
- `secret_key` (optional): The secret key provided as a string containing 32 hexadecimal characters
166+
- `data_format` (optional): The data format, provided as dictionnary matching the data format object specifications.
167+
168+
It provides the following methods:
169+
- `get_device_serial()`: Returns the serial number of the device as a string.
170+
- `set_device_parameters(secret_key, data_format)`: Used to set the device data required for proper processing of the request in the handler if it was not set initially, which is often the case as the serial number is usually required to fetch that data. It will return `ValueError` if either of the parameters is invalid.
171+
- `is_auth_valid()`: Returns `true` if the authentication provided is valid or `false` if not.
172+
- `get_simple_metrics()`: Returns the metrics provided in the simple expanded format. It will also convert relative timestamps into explicit timestamps for easier processing.
173+
- `expects_token_answer()`: Return `true` if the payload requested tokens in the answer. You can set the tokens to be returned by calling `add_tokens_to_answer(token_list)` with `token_list` being a list of token strings.
174+
- `expects_time_answer()`: Return `true` if the payload requested either relative time or absolute time in the answer. You can set the time to be returned by calling `add_time_to_answer(target_datetime)` with `target_datetime` being a datetime object. The function will automatically provide it in the correct format based on the request.
175+
- `add_settings_to_answer(settings_dict)`: Will add the provided settings dictionnary to the answer.
176+
- `add_extra_data_to_answer(extra_data_dict)`: Will add the provided extra data dictionnary to the answer.
177+
- `get_answer()`: Will return the answer as a string based on the request and the data added to answer, it will automatically handle the authentication and fomatting.
178+
179+
180+
**Example - Full Request flow:**
181+
182+
```python
183+
from openpaygo import MetricsHandler
184+
from my_db_service import get_device, store_metric
185+
186+
187+
@app.route('/dd')
188+
def device_data():
189+
# We load the metrics
190+
try:
191+
metrics = MetricsHandler(request.data)
192+
except ValueError as e:
193+
return {'error': 'Invalid data format'}, 400
194+
# We get the serial number and load the device data from our storage
195+
device = get_device(serial=metrics.get_device_serial())
196+
# We set the device parameters in the metrics handler
197+
metrics.set_device_parameters(
198+
secret_key=device.secret_key,
199+
data_format=device.data_format
200+
)
201+
# We check the authentication
202+
if not metrics.is_auth_valid():
203+
return {'error': 'Invalid authentication'}, 403
204+
# We transform the condensed data received from the device in simple data
205+
simple_data = metrics.get_simple_metrics()
206+
# We store the metrics in our database
207+
for metric_data in simple_data.get('data'):
208+
store_metric(name=metric_data['name'], value=metric_data['value'])
209+
for time_step in simple_data.get('historical_data'):
210+
for historical_metric_data in time_step:
211+
store_metric(name=metric_data['name'], value=metric_data['value'], time=time_step['timestamp'])
212+
# We prepare the answer
213+
if metrics.expects_token_answer():
214+
metrics.add_tokens_to_answer(device.pending_token_list)
215+
elif metrics.expects_time_answer():
216+
metrics.add_time_to_answer(device.expiration_datetime)
217+
# We can add extra data
218+
metrics.add_settings_to_answer({'language': 'fr-FR'})
219+
# The handler handles the signature, etc.
220+
return metrics.get_answer(), 200
221+
```
222+
223+
152224
## Changelog
153225

154226
### 2023-10-03 - v0.2.0

openpaygo/decode_metrics.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import json
2+
3+
4+
class MetricsHandler(object):
5+
6+
def __init__(self, received_metrics, data_format=None, secret_key=None):
7+
self.received_metrics = received_metrics
8+
self.metrics_dict = json.loads(received_metrics)
9+
self.answer_dict = {}
10+
11+
def get_device_serial(self):
12+
return self.received_metrics.get('sn', self.received_metrics.get('serial_number'))
13+
14+
def set_device_parameters(self, secret_key, data_format):
15+
pass
16+
17+
def is_auth_valid(self):
18+
pass
19+
20+
def get_simple_metrics(self):
21+
pass
22+
23+
def expects_token_answer(self):
24+
pass
25+
26+
def add_tokens_to_answer(self, token_list):
27+
pass
28+
29+
def expects_time_answer(self):
30+
pass
31+
32+
def add_time_to_answer(self, target_datetime):
33+
pass
34+
35+
def add_settings_to_answer(self, settings_dict):
36+
pass
37+
38+
def add_extra_data_to_answer(self, extra_data_dict):
39+
pass
40+
41+
def get_answer(self):
42+
pass
43+
44+
def _check_data_auth(self):
45+
data = self.metrics_dict.get('data', None)
46+
data_string = json.dumps(data, separators=(',', ':')) if data else ''
47+
historical_data = self.metrics_dict.get('historical_data', None)
48+
historical_data_string = json.dumps(historical_data, separators=(',', ':')) if historical_data else ''
49+

0 commit comments

Comments
 (0)