Skip to content

Commit fd7c6f7

Browse files
authored
Merge pull request #103 from ks6088ts-labs/feature/issue-102_iothub-api
add IoT Hub related APIs to backend
2 parents 9d8b4a0 + 3016e9d commit fd7c6f7

File tree

8 files changed

+314
-9
lines changed

8 files changed

+314
-9
lines changed

backend/fastapi.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from backend.routers import azure_ai_vision as azure_ai_vision_router
88
from backend.routers import azure_cosmos_db as azure_cosmos_db_router
99
from backend.routers import azure_event_grid as azure_event_grid_router
10+
from backend.routers import azure_iot_hub as azure_iot_hub_router
1011
from backend.routers import azure_openai as azure_openai_router
1112
from backend.routers import azure_storage_blob as azure_storage_blob_router
1213
from backend.routers import azure_storage_queue as azure_storage_queue_router
@@ -25,6 +26,7 @@
2526
azure_cosmos_db_router.router,
2627
azure_ai_speech_router.router,
2728
agents_router.router,
29+
azure_iot_hub_router.router,
2830
]:
2931
app.include_router(router)
3032

backend/internals/azure_iot_hub.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from logging import getLogger
2+
3+
from azure.iot.device.aio import IoTHubDeviceClient
4+
from azure.iot.hub import IoTHubRegistryManager
5+
from azure.iot.hub.models import CloudToDeviceMethod, CloudToDeviceMethodResult
6+
7+
from backend.settings.azure_iot_hub import Settings
8+
9+
logger = getLogger(__name__)
10+
11+
12+
class Client:
13+
def __init__(self, settings: Settings) -> None:
14+
self.settings = settings
15+
16+
async def get_device_twin(self) -> dict:
17+
client = IoTHubDeviceClient.create_from_connection_string(self.settings.azure_iot_hub_device_connection_string)
18+
# FIXME: to make it faster, connection should be established once and reused
19+
await client.connect()
20+
twin = await client.get_twin()
21+
await client.shutdown()
22+
return twin
23+
24+
def invoke_direct_method(
25+
self,
26+
method_name: str,
27+
payload: str,
28+
device_id: str,
29+
) -> dict:
30+
registry_manager = IoTHubRegistryManager(self.settings.azure_iot_hub_connection_string)
31+
# Call the direct method.
32+
deviceMethod = CloudToDeviceMethod(
33+
method_name=method_name,
34+
payload=payload,
35+
)
36+
response: CloudToDeviceMethodResult = registry_manager.invoke_device_method(
37+
device_id=device_id,
38+
direct_method_request=deviceMethod,
39+
)
40+
return response.as_dict()

backend/routers/azure_iot_hub.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from logging import getLogger
2+
3+
from fastapi import APIRouter, status
4+
from fastapi.responses import JSONResponse
5+
6+
from backend.internals.azure_iot_hub import Client
7+
from backend.settings.azure_iot_hub import Settings
8+
9+
logger = getLogger(__name__)
10+
11+
client = Client(
12+
settings=Settings(),
13+
)
14+
15+
router = APIRouter(
16+
prefix="/azure_iot_hub",
17+
tags=["azure_iot_hub"],
18+
responses={404: {"description": "Not found"}},
19+
)
20+
21+
22+
@router.get(
23+
"/device_twin",
24+
status_code=200,
25+
)
26+
async def get_device_twin():
27+
device_twin = await client.get_device_twin()
28+
return JSONResponse(
29+
status_code=status.HTTP_200_OK,
30+
content=device_twin,
31+
)
32+
33+
34+
@router.post(
35+
"/event_grid_event",
36+
status_code=200,
37+
)
38+
async def invoke_direct_method(
39+
device_id="device001",
40+
method_name="method1",
41+
payload={"hello": "world"},
42+
):
43+
response = client.invoke_direct_method(
44+
device_id=device_id,
45+
method_name=method_name,
46+
payload=payload,
47+
)
48+
return JSONResponse(
49+
status_code=status.HTTP_200_OK,
50+
content=response,
51+
)

backend/settings/azure_iot_hub.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from pydantic_settings import BaseSettings, SettingsConfigDict
2+
3+
4+
class Settings(BaseSettings):
5+
azure_iot_hub_device_connection_string: str = (
6+
"HostName=<iot-hub-name>.azure-devices.net;DeviceId=<device-name>;SharedAccessKey=<shared-access-key>"
7+
)
8+
azure_iot_hub_connection_string: str = (
9+
"HostName=<iot-hub-name>.azure-devices.net;SharedAccessKeyName=service;SharedAccessKey=<shared-access-key>"
10+
)
11+
12+
model_config = SettingsConfigDict(
13+
env_file="settings/azure_iot_hub.env",
14+
env_file_encoding="utf-8",
15+
)

docs/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@
102102

103103
- [Create and monitor a device](https://learn.microsoft.com/en-us/azure/iot-hub/quickstart-send-telemetry-cli#create-and-monitor-a-device)
104104
- [Connect Raspberry Pi to Azure IoT Hub](https://learn.microsoft.com/en-us/azure/iot-hub/raspberry-pi-get-started)
105+
- [Samples for the Azure IoT Hub Device SDK](https://github.com/Azure/azure-iot-sdk-python/blob/main/samples/README.md)
106+
- [Get started with device management (Python) > Create a service app to trigger a reboot](https://learn.microsoft.com/en-us/azure/iot-hub/device-management-python#create-a-service-app-to-trigger-a-reboot)
105107

106108
```shell
107109
IOT_HUB_NAME=""

0 commit comments

Comments
 (0)