2020-06-08 23:17:16 +02:00
|
|
|
#!/usr/bin/env python3
|
2020-06-21 23:34:54 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
|
|
#
|
|
|
|
# BITE - A Basic/IoT/Example
|
2021-03-21 16:18:44 +01:00
|
|
|
# Copyright (C) 2020-2021 Daniele Viganò <daniele@vigano.me>
|
2020-06-21 23:34:54 +02:00
|
|
|
#
|
|
|
|
# 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 <http://www.gnu.org/licenses/>.
|
2020-06-08 23:17:16 +02:00
|
|
|
|
|
|
|
import os
|
|
|
|
import json
|
|
|
|
import string
|
|
|
|
import random
|
|
|
|
import datetime
|
|
|
|
import urllib3
|
|
|
|
import argparse
|
|
|
|
|
|
|
|
from time import sleep
|
|
|
|
import paho.mqtt.publish as publish
|
|
|
|
|
2023-09-09 10:00:48 +02:00
|
|
|
DEBUG = bool(os.environ.get("IOT_DEBUG", False))
|
2020-06-08 23:17:16 +02:00
|
|
|
http = urllib3.PoolManager()
|
|
|
|
|
|
|
|
|
|
|
|
def post_json(endpoint, url, data):
|
|
|
|
json_data = json.dumps(data)
|
|
|
|
|
|
|
|
if DEBUG:
|
|
|
|
print(json_data)
|
|
|
|
|
2023-09-09 10:00:48 +02:00
|
|
|
encoded_data = json_data.encode("utf8")
|
2020-06-08 23:17:16 +02:00
|
|
|
|
|
|
|
while True:
|
|
|
|
try:
|
|
|
|
r = http.request(
|
2023-09-09 10:00:48 +02:00
|
|
|
"POST",
|
2020-06-08 23:17:16 +02:00
|
|
|
endpoint + url,
|
|
|
|
body=encoded_data,
|
2023-09-09 10:00:48 +02:00
|
|
|
headers={"content-type": "application/json"},
|
|
|
|
)
|
2020-06-08 23:17:16 +02:00
|
|
|
return r
|
|
|
|
except urllib3.exceptions.MaxRetryError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
sleep(10) # retry in 10 seconds
|
|
|
|
|
|
|
|
|
2020-06-21 15:21:00 +02:00
|
|
|
def publish_json(transport, endpoint, data):
|
2020-06-08 23:17:16 +02:00
|
|
|
json_data = json.dumps(data)
|
2023-09-09 10:00:48 +02:00
|
|
|
serial = data["device"]
|
2020-06-08 23:17:16 +02:00
|
|
|
|
|
|
|
if DEBUG:
|
|
|
|
print(json_data)
|
|
|
|
|
2023-09-09 10:00:48 +02:00
|
|
|
encoded_data = json_data.encode("utf8")
|
2020-06-08 23:17:16 +02:00
|
|
|
|
|
|
|
publish.single(
|
|
|
|
topic=serial,
|
|
|
|
payload=encoded_data,
|
2023-09-09 10:00:48 +02:00
|
|
|
hostname=endpoint.split(":")[0],
|
|
|
|
port=int(endpoint.split(":")[1]),
|
2020-06-08 23:17:16 +02:00
|
|
|
client_id=serial,
|
2023-09-09 10:00:48 +02:00
|
|
|
transport=("websockets" if transport == "ws" else "tcp"),
|
2020-06-08 23:17:16 +02:00
|
|
|
# auth=auth FIXME
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
2023-09-09 10:00:48 +02:00
|
|
|
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",
|
|
|
|
)
|
2020-06-08 23:17:16 +02:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
2023-09-09 11:35:06 +02:00
|
|
|
dps = "/dps/device/provision/"
|
2023-09-09 10:00:48 +02:00
|
|
|
telemetry = "/telemetry/"
|
2020-06-08 23:17:16 +02:00
|
|
|
|
|
|
|
if args.serial is None:
|
2023-09-09 10:00:48 +02:00
|
|
|
args.serial = "".join(
|
|
|
|
random.choices(string.ascii_lowercase + string.digits, k=8)
|
|
|
|
)
|
2020-06-08 23:17:16 +02:00
|
|
|
|
2023-09-09 10:00:48 +02:00
|
|
|
data = {"serial": args.serial}
|
2023-09-09 11:24:00 +02:00
|
|
|
post_json(args.endpoint, dps, data)
|
2020-06-08 23:17:16 +02:00
|
|
|
|
|
|
|
while True:
|
2020-06-10 23:17:30 +02:00
|
|
|
data = {
|
2023-09-09 10:00:48 +02:00
|
|
|
"device": args.serial,
|
|
|
|
"clock": int(datetime.datetime.now().timestamp()),
|
2020-06-10 23:17:30 +02:00
|
|
|
}
|
2020-06-08 23:17:16 +02:00
|
|
|
payload = {
|
2023-09-09 10:00:48 +02:00
|
|
|
"id": "device_simulator",
|
|
|
|
"light": random.randint(300, 500),
|
|
|
|
"temperature": {"celsius": round(random.uniform(20, 28), 1)},
|
2020-06-08 23:17:16 +02:00
|
|
|
}
|
2023-09-09 10:00:48 +02:00
|
|
|
if args.transport == "http":
|
|
|
|
post_json(args.endpoint, telemetry, {**data, "payload": payload})
|
|
|
|
elif args.transport in ("mqtt", "ws"):
|
2020-06-21 15:21:00 +02:00
|
|
|
publish_json(
|
2023-09-09 10:00:48 +02:00
|
|
|
args.transport, args.mqtt, {**data, "payload": payload}
|
|
|
|
)
|
2020-06-08 23:17:16 +02:00
|
|
|
else:
|
|
|
|
raise NotImplementedError
|
|
|
|
sleep(args.delay)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|