{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Running the fleet of Virtual Wind Turbines and Edge Devices\n", "\n", "**SageMaker Studio Kernel**: Data Science\n", "\n", "After visualizing the data and training/optimizing/packaging the Anomaly detection model, its time to deploy it and test your virtual fleet. In this exercise you will run a local application written in Python3 that simulates 5 Wind Turbines and 5 edge devices. The SageMaker Edge Agent is deployed on the edge devices.\n", "\n", "Here you'll be the **Wind Turbine Farm Operator**. It's possible to visualize the data flowing from the sensors to the ML Model and analyze the anomalies. Also, you'll be able to inject noise (pressing some buttons) in the data to simulate potential anomalies with the equipment.\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
STEP-BY-STEPAPPLICATION ARCHITECTURE
\n", "\n", "The components of the applicationare:\n", " - Simulator:\n", " - [Simulator](app/ota.py): Program that launches the virtual wind turbines and the edge devices. It uses Python Threads to run all the 10 processes\n", " - [Wind Farm](app/windfarm.py): This is the application that runs on the edge device. It is reponsible for reading the sensors, invoking the ML model and analyzing the anomalies \n", " - Edge Application:\n", " - [Turbine](app/turbine.py): Virtual Wind Turbine. It reads the raw data collected from the 3D Prited Mini Turbine and stream it as a circular buffer. It also has a graphical representation in **IPython Widgets** that is rendered by the Simulator/Dashboard.\n", " - [Over The Air](app/ota.py): This is a module integrated with **IoT Jobs**. In the previous exercise you created an IoT job to deploy the model. This module gets the document process it and deployes the model in each edge device and loads it via SageMaker Edge Manager.\n", " - [Edge client](app/edgeagentclient.py): An abstraction layer on top of the **generated stubs** (proto compilation). It makes it easy to integrate **Wind Farm** with the SageMaker Edge Agent" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Install some dependencies" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!apt-get -y update && apt-get -y install build-essential procps\n", "!pip install -U grpcio-tools grpcio protobuf\n", "!pip install paho-mqtt\n", "!pip install ipywidgets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Download the sensors data (streamed by the virtual wind turbines)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!mkdir -p data\n", "!curl https://aws-ml-blog.s3.amazonaws.com/artifacts/monitor-manage-anomaly-detection-model-wind-turbine-fleet-sagemaker-neo/dataset_wind_turbine.csv.gz -o data/dataset_wind.csv.gz" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import boto3\n", "import tarfile\n", "import os\n", "import stat\n", "import io" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "project_name='<>'\n", "\n", "sm_client = boto3.client('sagemaker')\n", "project_id = sm_client.describe_project(ProjectName=project_name)['ProjectId']\n", "bucket_name = 'sagemaker-wind-turbine-farm-%s' % project_id\n", "\n", "agent_config_package_prefix = 'wind_turbine_agent/config.tgz'\n", "agent_version = '1.20210512.96da6cc'\n", "agent_pkg_bucket = 'sagemaker-edge-release-store-us-west-2-linux-x64'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Prepare the edge devices\n", " 1. First download the deployment package that contains the IoT + CA certificates and the configuration file of the SageMaker Edge Agent. \n", " 2. Then, download the SageMaker Edge Manager package and complete the deployment process.\n", " \n", " > You can see all the artifacts that will be loaded/executed by the virtual Edge Device in **agent/**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if not os.path.isdir('agent'):\n", " s3_client = boto3.client('s3')\n", "\n", " # Get the configuration package with certificates and config files\n", " with io.BytesIO() as file:\n", " s3_client.download_fileobj(bucket_name, agent_config_package_prefix, file)\n", " file.seek(0)\n", " # Extract the files\n", " tar = tarfile.open(fileobj=file)\n", " tar.extractall('.')\n", " tar.close() \n", "\n", " # Download and install SageMaker Edge Manager\n", " agent_pkg_key = 'Releases/%s/%s.tgz' % (agent_version, agent_version)\n", " # get the agent package\n", " with io.BytesIO() as file:\n", " s3_client.download_fileobj(agent_pkg_bucket, agent_pkg_key, file)\n", " file.seek(0)\n", " # Extract the files\n", " tar = tarfile.open(fileobj=file)\n", " tar.extractall('agent')\n", " tar.close()\n", " # Adjust the permissions\n", " os.chmod('agent/bin/sagemaker_edge_agent_binary', stat.S_IXUSR|stat.S_IWUSR|stat.S_IXGRP|stat.S_IWGRP)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Finally, create the SageMaker Edge Agent client stubs, using the protobuffer compiler" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!python3 -m grpc_tools.protoc --proto_path=agent/docs/api --python_out=app/ --grpc_python_out=app/ agent/docs/api/agent.proto" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Simulating The Wind Turbine Farm\n", "Now its time to run our simulator and start playing with the turbines, agents and with the anomalies\n", " > After clicking on **Start**, each turbine will start buffering some data. It takes a few seconds but after completing this process, the application runs in real-time \n", " > Try to press some buttons while the simulation is running, to inject noise in the data and see some anomalies \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import sys\n", "sys.path.insert(1, 'app')\n", "import windfarm\n", "import edgeagentclient\n", "import turbine\n", "import simulator\n", "import ota\n", "import boto3\n", "from importlib import reload\n", "\n", "reload(simulator)\n", "reload(turbine)\n", "reload(edgeagentclient)\n", "reload(windfarm)\n", "reload(ota)\n", "\n", "iot_client = boto3.client('iot')\n", "\n", "mqtt_host=iot_client.describe_endpoint(endpointType='iot:Data-ATS')['endpointAddress']\n", "mqtt_port=8883\n", "\n", "!mkdir -p agent/logs && rm -f agent/logs/*\n", "simulator = simulator.WindTurbineFarmSimulator(5)\n", "simulator.start()\n", "\n", "farm = windfarm.WindTurbineFarm(simulator, mqtt_host, mqtt_port)\n", "farm.start()\n", "\n", "simulator.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " > If you want to experiment with the deployment process, with the wind farm running, go back to [Exercise #2](02%20-%20Training%20with%20Pytorch.ipynb#Building-the-Deployment-Package-SageMaker-Edge-Manager) (in the last cells), replace the variable **model_version** by the constant (string) '2.0' in the Json document used by the IoT Job. Then, create a new IoT Job to simulate how to deploy new versions of the model. Go back to this exercise to see the results." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "farm.halt()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "----" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Cleanup\n", "Run the next cell only if you already finished exploring/hacking the content of the workshop. \n", "This code will delete all the resouces created so far, including the **SageMaker Project** you've created" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import boto3\n", "import time\n", "from shutil import rmtree\n", "\n", "iot_client = boto3.client('iot')\n", "sm_client = boto3.client('sagemaker')\n", "s3_resource = boto3.resource('s3')\n", "\n", "policy_name='WindTurbineFarmPolicy-%s' % project_id\n", "thing_group_name='WindTurbineFarm-%s' % project_id\n", "fleet_name='wind-turbine-farm-%s' % project_id\n", "\n", "# Delete all files from the S3 Bucket\n", "s3_resource.Bucket(bucket_name).objects.all().delete()\n", "\n", "# now deregister the devices from the fleet\n", "resp = sm_client.list_devices(DeviceFleetName=fleet_name)\n", "devices = [d['DeviceName'] for d in resp['DeviceSummaries']]\n", "if len(devices) > 0:\n", " sm_client.deregister_devices(DeviceFleetName=fleet_name, DeviceNames=devices)\n", "\n", "# now deregister the devices from the fleet\n", "for i,cert_arn in enumerate(iot_client.list_targets_for_policy(policyName=policy_name)['targets']):\n", " for t in iot_client.list_principal_things(principal=cert_arn)['things']:\n", " iot_client.detach_thing_principal(thingName=t, principal=cert_arn)\n", " iot_client.detach_policy(policyName=policy_name, target=cert_arn)\n", " certificateId = cert_arn.split('/')[-1]\n", "\n", "iot_client.delete_role_alias(roleAlias='SageMakerEdge-%s' % fleet_name)\n", "iot_client.delete_thing_group(thingGroupName=thing_group_name)\n", "\n", "if os.path.isdir('agent'): rmtree('agent')\n", "sm_client.delete_project(ProjectName=project_name)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mission Complete! \n", "Congratulations! :)" ] } ], "metadata": { "instance_type": "ml.t3.medium", "kernelspec": { "display_name": "Python 3 (Data Science)", "language": "python", "name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:us-east-1:081325390199:image/datascience-1.0" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.10" } }, "nbformat": 4, "nbformat_minor": 4 }