diff options
author | Michael Abel <75477722+abelikt@users.noreply.github.com> | 2021-04-09 12:20:06 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-09 12:20:06 +0200 |
commit | 9bce25c637b26eff390935999f96265a71b23913 (patch) | |
tree | 381e916d6dc54e6cd203c6a20cf589c12d9a8c7b /ci | |
parent | d17d0ad57bcd857fdbfa4c95a3ae7ab096306919 (diff) |
[CIT-279] Improve roundtrip test script (#164)
- Add optional command line parameters for size, timeslot size and delay
- Increase c8y page size
- Adopt user model and use sudo
- Add more checks for the c8y response
- Remove timezone management and use UTC instead
Signed-off-by: Michael Abel <info@abel-ikt.de>
Diffstat (limited to 'ci')
-rwxr-xr-x | ci/roundtrip_local_to_c8y.py | 104 |
1 files changed, 77 insertions, 27 deletions
diff --git a/ci/roundtrip_local_to_c8y.py b/ci/roundtrip_local_to_c8y.py index e01f2eee..ba68c8b5 100755 --- a/ci/roundtrip_local_to_c8y.py +++ b/ci/roundtrip_local_to_c8y.py @@ -3,7 +3,10 @@ """ This is a hack to do a full roundtrip of data from thin-edge to c8y and back. -It publishes numbers from 0..19 and expects to read them back from the cloud. +It publishes a sequence of numbers and expects to read them back from the cloud. +For thin-edge JSON the sawtooth publisher is used to publish. +For SmartREST the tedge is used to publish. + Call example: ./roundtrip_local_to_c8y.py -m REST -pub ~/thin-edge.io/target/debug/examples/ -u <username> -t <tennant> -pass <pass> -id <id> @@ -20,49 +23,50 @@ import time import requests # Warning: the list begins with the earliest one -PAGE_SIZE = "200" +PAGE_SIZE = "500" -# Seconds to retrieve from the past (smaller than 10 does not work all the time) -TIMESLOT = 10 +# sudo is currently needed to avoid "User's Home Directory not found." +CMD_PUBLISH_REST = "sudo tedge mqtt pub c8y/s/us 211,%i" -CMD_PUBLISH_REST = "tedge mqtt pub c8y/s/us 211,%i" -CMD_PUBLISH_JSON = "sawtooth_publisher 100 20 1 flux" +CMD_PUBLISH_JSON = "sawtooth_publisher %s %s 1 flux" -def act(path_publisher, mode): +def act(path_publisher, mode, publish_amount, delay): """Act: Publishing values with temperature_publisher""" if mode == "JSON": print("Act: Publishing values with temperature_publisher") - ret = os.system(os.path.join(path_publisher, CMD_PUBLISH_JSON)) + ret = os.system( + os.path.join(path_publisher, CMD_PUBLISH_JSON % (delay, publish_amount)) + ) if ret != 0: print("Error cannot run publisher") sys.exit(1) elif mode == "REST": print("Act: Publishing values with tedge pub") - for i in range(0, 20): + for i in range(0, int(publish_amount)): ret = os.system(CMD_PUBLISH_REST % i) if ret != 0: print("Error cannot run publisher") sys.exit(1) - time.sleep(0.1) + time.sleep(delay / 1000) else: sys.exit(1) - print("Waiting 2s for values to arrive in C8y") + print("Waiting 3s for values to arrive in C8y") - time.sleep(2) + time.sleep(3) -def retrieve_data(user, device_id, password, tenant, verbose): +def retrieve_data(user, device_id, password, tenant, verbose, timeslot): """Download via REST""" time_to = datetime.utcnow().replace(microsecond=0) - time_from = time_to - timedelta(seconds=TIMESLOT) + time_from = time_to - timedelta(seconds=timeslot) - date_from = time_from.isoformat(sep="T") + 'Z' - date_to = time_to.isoformat(sep="T") + 'Z' + date_from = time_from.isoformat(sep="T") + "Z" + date_to = time_to.isoformat(sep="T") + "Z" print(f"Gathering values from {time_from} to {time_to}") @@ -117,12 +121,20 @@ def check_timestamps(timestamps, laststamp): tstampiso = datetime.fromisoformat(tstamp) + warning = 0 + if tstampiso > laststamp: laststamp = tstampiso + if tstampiso == laststamp: + laststamp = tstampiso + warning += 1 else: print("Oops", tstampiso, "is smaller than", laststamp) failed = True + if warning: + print(f"WARNING: found {warning} equal timestamps!") + if not failed: print("Timestamp verification PASSED") else: @@ -130,29 +142,50 @@ def check_timestamps(timestamps, laststamp): sys.exit(1) -def assert_values(mode, user, device_id, password, tenant, verbose): +def assert_values( + mode, user, device_id, password, tenant, verbose, publish_amount, timeslot +): """Assert: Retrieving data via REST interface""" print("Assert: Retrieving data via REST interface") - req, time_from = retrieve_data(user, device_id, password, tenant, verbose) + req, time_from = retrieve_data(user, device_id, password, tenant, verbose, timeslot) + + response = req.json() + + assert "statistics" in response + page_size = response["statistics"]["pageSize"] amount = len(req.json()["measurements"]) print(f"Found {amount} recorded values: ") + if page_size == amount: + print(f"Got {amount} values: your page size {page_size} is probably to small!") + sys.exit(1) + values = [] timestamps = [] - for i in req.json()["measurements"]: + assert "measurements" in response + + for i in response["measurements"]: + source = i["source"]["id"] + assert source == device_id if mode == "JSON": + + assert i["type"] == "ThinEdgeMeasurement" + try: value = i["Flux [F]"]["Flux [F]"]["value"] except KeyError: print(f"Error: Cannot parse response: {i}") sys.exit(1) elif mode == "REST": + + assert i["type"] == "c8y_TemperatureMeasurement" + try: value = i["c8y_TemperatureMeasurement"]["T"]["value"] except KeyError: @@ -168,7 +201,7 @@ def assert_values(mode, user, device_id, password, tenant, verbose): values.append(value) timestamps.append(tstamp) - expected = list(range(0, 20)) + expected = list(range(0, int(publish_amount))) print("Retrieved:", values) print("Expected:", expected) @@ -182,7 +215,8 @@ def assert_values(mode, user, device_id, password, tenant, verbose): check_timestamps(timestamps, time_from) -if __name__ == "__main__": +def main(): + """The 'main' function""" parser = argparse.ArgumentParser() parser.add_argument("-m", "--mode", help="Mode JSON or REST") @@ -191,7 +225,14 @@ if __name__ == "__main__": parser.add_argument("-t", "--tenant", help="C8y tenant") parser.add_argument("-pass", "--password", help="C8y Password") parser.add_argument("-id", "--id", help="Device ID for C8y") - parser.add_argument('--verbose', '-v', action='count', default=0) + parser.add_argument("--verbose", "-v", action="count", default=0) + parser.add_argument( + "--size", "-s", type=int, help="Amount of values to publish", default=20 + ) + parser.add_argument("--slot", "-o", type=int, help="Timeslot size", default=10) + parser.add_argument( + "--delay", "-d", type=int, help="Delay between publishs", default=100 + ) args = parser.parse_args() mode = args.mode @@ -202,14 +243,23 @@ if __name__ == "__main__": tenant = args.tenant password = args.password device_id = args.id + publish_amount = args.size + timeslot = args.slot + delay = args.delay if verbose: print(f"Mode: {mode}") print(f"Using path for publisher: {path_publisher}") - print(f"Using user name: HIDDEN") - print(f"Using tenant-id: HIDDEN") - print(f"Using device-id: HIDDEN") + print("Using user name: HIDDEN") + print("Using tenant-id: HIDDEN") + print("Using device-id: HIDDEN") + + act(path_publisher, mode, publish_amount, delay) - act(path_publisher, mode) + assert_values( + mode, user, device_id, password, tenant, verbose, publish_amount, timeslot + ) - assert_values(mode, user, device_id, password, tenant, verbose) + +if __name__ == "__main__": + main() |