#!/usr/bin/env python3 # -*- coding: utf-8 -*- # vim: tabstop=4 shiftwidth=4 softtabstop=4 # # BITE - A Basic/IoT/Example # Copyright (C) 2020-2021 Daniele ViganĂ² # # BITE is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # BITE is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import os import json import string import random import datetime import urllib3 import argparse from time import sleep import paho.mqtt.publish as publish DEBUG = bool(os.environ.get('IOT_DEBUG', False)) http = urllib3.PoolManager() def post_json(endpoint, url, data): json_data = json.dumps(data) if DEBUG: print(json_data) encoded_data = json_data.encode('utf8') while True: try: r = http.request( 'POST', endpoint + url, body=encoded_data, headers={'content-type': 'application/json'}) return r except urllib3.exceptions.MaxRetryError: pass sleep(10) # retry in 10 seconds def publish_json(transport, endpoint, data): json_data = json.dumps(data) serial = data['device'] if DEBUG: print(json_data) encoded_data = json_data.encode('utf8') publish.single( topic=serial, payload=encoded_data, hostname=endpoint.split(':')[0], port=int(endpoint.split(':')[1]), client_id=serial, transport=('websockets' if transport == 'ws' else 'tcp'), # auth=auth FIXME ) def main(): parser = argparse.ArgumentParser( description='IoT simulator oprions') parser.add_argument('-e', '--endpoint', default=os.environ.get('IOT_HTTP', 'http://127.0.0.1:8000'), help='IoT HTTP endpoint') parser.add_argument('-m', '--mqtt', default=os.environ.get('IOT_MQTT', '127.0.0.1:1883'), help='IoT MQTT endpoint') parser.add_argument('-t', '--transport', choices=['mqtt', 'ws', 'http'], default=os.environ.get('IOT_TL', 'http'), help='IoT transport layer') parser.add_argument('-s', '--serial', default=os.environ.get('IOT_SERIAL'), help='IoT device serial number') parser.add_argument('-d', '--delay', metavar='s', type=float, default=os.environ.get('IOT_DELAY', 10), help='Delay between requests') args = parser.parse_args() subscribe = '/api/device/subscribe/' telemetry = '/telemetry/' if args.serial is None: args.serial = ''.join( random.choices(string.ascii_lowercase + string.digits, k=8)) data = {'serial': args.serial} post_json(args.endpoint, subscribe, data) while True: data = { 'device': args.serial, 'clock': int(datetime.datetime.now().timestamp()), } payload = { 'id': 'device_simulator', 'light': random.randint(300, 500), 'temperature': { 'celsius': round(random.uniform(20, 28), 1)} } if args.transport == 'http': post_json(args.endpoint, telemetry, {**data, 'payload': payload}) elif args.transport in ('mqtt', 'ws'): publish_json( args.transport, args.mqtt, {**data, 'payload': payload}) else: raise NotImplementedError sleep(args.delay) if __name__ == "__main__": main()