================================================================================
  Experiment 7: ThingsBoard MQTT Telemetry Simulation
================================================================================

FULL QUESTION:
Develop an IoT application that simulates temperature and humidity sensor data, publishes the data to ThingsBoard using the MQTT protocol, and visualizes the sensor readings on the ThingsBoard dashboard.

SHORT QUESTION:
Simulate environmental telemetry and publish to ThingsBoard Cloud via MQTT with custom dashboard.

================================================================================
README & SETUP INSTRUCTIONS:
================================================================================
# Experiment 7: ThingsBoard MQTT Telemetry Simulation

## Objective
Simulate environmental sensor telemetry and publish continuous JSON packets to ThingsBoard Cloud using MQTT protocol.

## Requirements
```bash
pip install paho-mqtt
```

## Setup Instructions
1. Create a free account at [thingsboard.cloud](https://thingsboard.cloud).
2. Go to **Device Management -> Devices** and click **Add Device**.
3. Under **Device Credentials**, copy your **Access Token**.
4. Replace `ACCESS_TOKEN` in `simulate_thingsboard.py`.
5. Run the simulator:
   ```bash
   python simulate_thingsboard.py
   ```
6. Open ThingsBoard -> Dashboards to create Gauge/Time-series widgets for `temperature` and `humidity`.

================================================================================
SOURCE CODE FILES:
================================================================================

1. simulate_thingsboard.py
--------------------------------------------------------------------------------
import time
import json
import random
import paho.mqtt.client as mqtt

THINGSBOARD_HOST = "thingsboard.cloud"
ACCESS_TOKEN = "XizYQ9mMsrFXPXID8Xrc"

try:
    client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
except AttributeError:
    client = mqtt.Client()

client.username_pw_set(ACCESS_TOKEN)
client.connect(THINGSBOARD_HOST, 1883, 60)
client.loop_start()

print("Connected to ThingsBoard. Streaming telemetry...")

try:
    while True:
        telemetry = {
            "temperature": round(random.uniform(20.0, 35.0), 2),
            "humidity": round(random.uniform(40.0, 80.0), 2)
        }
        client.publish("v1/devices/me/telemetry", json.dumps(telemetry))
        print("Published telemetry:", telemetry)
        time.sleep(1)
except KeyboardInterrupt:
    client.loop_stop()
    client.disconnect()
    print("Stream stopped.")
--------------------------------------------------------------------------------

2. environmental_dashboard.json
--------------------------------------------------------------------------------
{
  "title": "Environmental Telemetry Dashboard",
  "image": null,
  "mobileHide": false,
  "mobileOrder": null,
  "configuration": {
    "description": "Live visualization for simulated temperature and humidity telemetry",
    "widgets": {
      "widget_gauge_temp": {
        "isFullWidth": false,
        "type": "latest",
        "sizeX": 6,
        "sizeY": 5,
        "row": 0,
        "col": 0,
        "config": {
          "title": "Temperature Gauge",
          "datasources": [
            {
              "type": "entity",
              "entityAliasId": "current_device_alias",
              "dataKeys": [
                {
                  "name": "temperature",
                  "type": "timeseries",
                  "label": "Temperature",
                  "color": "#d9534f",
                  "settings": {
                    "minValue": 0,
                    "maxValue": 50,
                    "unitTitle": "°C"
                  }
                }
              ]
            }
          ],
          "showTitle": true,
          "backgroundColor": "#ffffff",
          "color": "rgba(0, 0, 0, 0.87)",
          "padding": "16px",
          "settings": {
            "minValue": 0,
            "maxValue": 50,
            "unitTitle": "°C",
            "gaugeType": "arc"
          }
        },
        "typeFullFqn": "system.cards.radial_gauge_card"
      },
      "widget_gauge_hum": {
        "isFullWidth": false,
        "type": "latest",
        "sizeX": 6,
        "sizeY": 5,
        "row": 0,
        "col": 6,
        "config": {
          "title": "Humidity Gauge",
          "datasources": [
            {
              "type": "entity",
              "entityAliasId": "current_device_alias",
              "dataKeys": [
                {
                  "name": "humidity",
                  "type": "timeseries",
                  "label": "Humidity",
                  "color": "#0275d8",
                  "settings": {
                    "minValue": 0,
                    "maxValue": 100,
                    "unitTitle": "%"
                  }
                }
              ]
            }
          ],
          "showTitle": true,
          "backgroundColor": "#ffffff",
          "color": "rgba(0, 0, 0, 0.87)",
          "padding": "16px",
          "settings": {
            "minValue": 0,
            "maxValue": 100,
            "unitTitle": "%",
            "gaugeType": "arc"
          }
        },
        "typeFullFqn": "system.cards.radial_gauge_card"
      },
      "widget_timeseries_chart": {
        "isFullWidth": true,
        "type": "timeseries",
        "sizeX": 12,
        "sizeY": 6,
        "row": 5,
        "col": 0,
        "config": {
          "title": "Real-Time Telemetry Trends",
          "datasources": [
            {
              "type": "entity",
              "entityAliasId": "current_device_alias",
              "dataKeys": [
                {
                  "name": "temperature",
                  "type": "timeseries",
                  "label": "Temperature (°C)",
                  "color": "#f0ad4e"
                },
                {
                  "name": "humidity",
                  "type": "timeseries",
                  "label": "Humidity (%)",
                  "color": "#5bc0de"
                }
              ]
            }
          ],
          "showTitle": true,
          "backgroundColor": "#ffffff",
          "color": "rgba(0, 0, 0, 0.87)",
          "padding": "16px",
          "settings": {
            "shadowSize": 4,
            "smoothLines": true,
            "comparisonEnabled": false,
            "xaxis": {
              "showLabels": true
            },
            "yaxis": {
              "showLabels": true
            }
          }
        },
        "typeFullFqn": "system.charts.flot"
      }
    },
    "states": {
      "default": {
        "name": "Default State",
        "root": true,
        "layouts": {
          "main": {
            "widgets": {
              "widget_gauge_temp": {},
              "widget_gauge_hum": {},
              "widget_timeseries_chart": {}
            },
            "gridSettings": {
              "backgroundColor": "#f4f6f9",
              "columns": 12,
              "margin": 10
            }
          }
        }
      }
    },
    "entityAliases": {
      "current_device_alias": {
        "id": "current_device_alias",
        "alias": "Environmental Sensor",
        "filter": {
          "type": "singleEntity",
          "singleEntity": {
            "entityType": "DEVICE",
            "id": "CURRENT_DEVICE_ID"
          }
        }
      }
    },
    "timewindow": {
      "displayValue": "",
      "hideInterval": false,
      "hideAggregation": false,
      "hideAggInterval": false,
      "hideTimezone": false,
      "selectedTab": 0,
      "realtime": {
        "realtimeType": 0,
        "interval": 1000,
        "timewindowMs": 60000
      },
      "aggregation": {
        "type": "NONE",
        "limit": 200
      }
    }
  }
}
--------------------------------------------------------------------------------
