0
# Greengrass Discovery
1
2
Discovery service for finding and connecting to AWS Greengrass Core devices in local networks. Enables devices to discover Greengrass cores, retrieve connectivity information, and obtain CA certificates for establishing secure connections within the Greengrass group.
3
4
## Capabilities
5
6
### Discovery Provider
7
8
Create a discovery client to find Greengrass cores and retrieve connectivity information for local communication.
9
10
```python { .api }
11
class DiscoveryInfoProvider:
12
def __init__(self, caPath: str = "", certPath: str = "", keyPath: str = "", host: str = "", port: int = 8443, timeoutSec: int = 120):
13
"""
14
Create Greengrass discovery client.
15
16
Args:
17
caPath (str): Path to root CA certificate file
18
certPath (str): Path to device certificate file
19
keyPath (str): Path to private key file
20
host (str): Discovery service endpoint hostname
21
port (int): Discovery service port (default 8443)
22
timeoutSec (int): Discovery request timeout in seconds
23
"""
24
```
25
26
### Discovery Configuration
27
28
Configure discovery endpoint, credentials, and timeout settings.
29
30
```python { .api }
31
def configureEndpoint(self, host: str, port: int = 8443):
32
"""
33
Configure discovery service endpoint.
34
35
Args:
36
host (str): Discovery service hostname
37
port (int): Discovery service port (default 8443)
38
"""
39
40
def configureCredentials(self, caPath: str, certPath: str, keyPath: str):
41
"""
42
Configure X.509 certificate credentials for discovery authentication.
43
44
Args:
45
caPath (str): Path to root CA certificate file
46
certPath (str): Path to device certificate file
47
keyPath (str): Path to private key file
48
"""
49
50
def configureTimeout(self, timeoutSec: int):
51
"""
52
Configure discovery request timeout.
53
54
Args:
55
timeoutSec (int): Timeout in seconds for discovery requests
56
"""
57
```
58
59
### Discovery Operations
60
61
Perform discovery requests to find Greengrass cores and retrieve connectivity information.
62
63
```python { .api }
64
def discover(self, thingName: str) -> 'DiscoveryInfo':
65
"""
66
Discover Greengrass cores for the specified thing.
67
68
Args:
69
thingName (str): AWS IoT thing name to discover cores for
70
71
Returns:
72
DiscoveryInfo: Discovery results with core connectivity information
73
74
Raises:
75
DiscoveryTimeoutException: Discovery request timed out
76
DiscoveryUnauthorizedException: Authentication failed
77
DiscoveryDataNotFoundException: No discovery data found for thing
78
"""
79
```
80
81
## Discovery Data Models
82
83
Data structures for managing Greengrass discovery information and connectivity details.
84
85
### DiscoveryInfo
86
87
Container for all discovery information including cores, groups, and CA certificates.
88
89
```python { .api }
90
class DiscoveryInfo:
91
def getAllCores(self) -> list:
92
"""
93
Get all core connectivity information.
94
95
Returns:
96
list: List of CoreConnectivityInfo objects
97
"""
98
99
def getAllCas(self) -> list:
100
"""
101
Get all CA certificates from discovery.
102
103
Returns:
104
list: List of (groupId, caContent) tuples
105
"""
106
107
def getAllGroups(self) -> list:
108
"""
109
Get all group connectivity information.
110
111
Returns:
112
list: List of GroupConnectivityInfo objects
113
"""
114
115
def toObjectAtGroupLevel(self) -> dict:
116
"""
117
Convert discovery info to group-level dictionary structure.
118
119
Returns:
120
dict: Dictionary with groupId keys and GroupConnectivityInfo values
121
"""
122
```
123
124
### GroupConnectivityInfo
125
126
Connectivity information for a Greengrass group containing cores and CA certificates.
127
128
```python { .api }
129
class GroupConnectivityInfo:
130
# Properties
131
groupId: str # Greengrass group ID
132
coreConnectivityInfoList: list # List of CoreConnectivityInfo objects
133
caList: list # List of CA certificates for this group
134
135
def getCoreConnectivityInfo(self, coreThingArn: str) -> 'CoreConnectivityInfo':
136
"""
137
Get connectivity info for specific core by ARN.
138
139
Args:
140
coreThingArn (str): Core thing ARN to find
141
142
Returns:
143
CoreConnectivityInfo: Connectivity info for the specified core
144
"""
145
146
def appendCoreConnectivityInfo(self, coreConnectivityInfo: 'CoreConnectivityInfo'):
147
"""
148
Add core connectivity information to this group.
149
150
Args:
151
coreConnectivityInfo (CoreConnectivityInfo): Core connectivity info to add
152
"""
153
154
def appendCa(self, ca: str):
155
"""
156
Add CA certificate to this group.
157
158
Args:
159
ca (str): CA certificate content to add
160
"""
161
```
162
163
### CoreConnectivityInfo
164
165
Connectivity information for a specific Greengrass core device.
166
167
```python { .api }
168
class CoreConnectivityInfo:
169
# Properties
170
coreThingArn: str # Core thing ARN
171
groupId: str # Associated group ID
172
connectivityInfoList: list # List of ConnectivityInfo objects
173
174
def getConnectivityInfo(self, id: str) -> 'ConnectivityInfo':
175
"""
176
Get connectivity info by ID.
177
178
Args:
179
id (str): Connectivity info ID to find
180
181
Returns:
182
ConnectivityInfo: Connectivity information for the specified ID
183
"""
184
185
def appendConnectivityInfo(self, connectivityInfo: 'ConnectivityInfo'):
186
"""
187
Add connectivity information to this core.
188
189
Args:
190
connectivityInfo (ConnectivityInfo): Connectivity info to add
191
"""
192
```
193
194
### ConnectivityInfo
195
196
Individual connectivity endpoint information for reaching a Greengrass core.
197
198
```python { .api }
199
class ConnectivityInfo:
200
# Properties
201
id: str # Connectivity info ID
202
host: str # Hostname or IP address
203
port: int # Port number
204
metadata: dict # Additional metadata
205
```
206
207
## Usage Examples
208
209
### Basic Discovery
210
211
```python
212
from AWSIoTPythonSDK.core.greengrass.discovery.providers import DiscoveryInfoProvider
213
from AWSIoTPythonSDK.exception.AWSIoTExceptions import DiscoveryTimeoutException
214
import json
215
216
# Create discovery provider
217
discoveryInfoProvider = DiscoveryInfoProvider()
218
219
# Configure discovery endpoint
220
discoveryInfoProvider.configureEndpoint("greengrass-ats.iot.region.amazonaws.com")
221
222
# Configure credentials
223
discoveryInfoProvider.configureCredentials(
224
"rootCA.crt",
225
"certificate.crt",
226
"private.key"
227
)
228
229
# Configure timeout
230
discoveryInfoProvider.configureTimeout(10)
231
232
try:
233
# Perform discovery
234
discoveryInfo = discoveryInfoProvider.discover("myThingName")
235
236
# Get all discovered cores
237
cores = discoveryInfo.getAllCores()
238
print(f"Discovered {len(cores)} Greengrass cores")
239
240
# Get all CA certificates
241
cas = discoveryInfo.getAllCas()
242
print(f"Retrieved {len(cas)} CA certificates")
243
244
# Print discovery results
245
for core in cores:
246
print(f"Core: {core.coreThingArn}")
247
print(f"Group: {core.groupId}")
248
for conn_info in core.connectivityInfoList:
249
print(f" Endpoint: {conn_info.host}:{conn_info.port}")
250
251
except DiscoveryTimeoutException:
252
print("Discovery request timed out")
253
except Exception as e:
254
print(f"Discovery failed: {e}")
255
```
256
257
### Core Selection and Connection
258
259
```python
260
from AWSIoTPythonSDK.core.greengrass.discovery.providers import DiscoveryInfoProvider
261
import AWSIoTPythonSDK.MQTTLib as AWSIoTPyMQTT
262
import json
263
import ssl
264
import tempfile
265
import os
266
267
# Perform discovery
268
discoveryInfoProvider = DiscoveryInfoProvider()
269
discoveryInfoProvider.configureEndpoint("greengrass-ats.iot.region.amazonaws.com")
270
discoveryInfoProvider.configureCredentials("rootCA.crt", "certificate.crt", "private.key")
271
272
discoveryInfo = discoveryInfoProvider.discover("myDevice")
273
274
# Get group-level information
275
groups = discoveryInfo.toObjectAtGroupLevel()
276
277
for group_id, group_info in groups.items():
278
print(f"Processing group: {group_id}")
279
280
# Write group CA certificates to temporary files
281
ca_files = []
282
for i, (_, ca_content) in enumerate(group_info.caList):
283
ca_file = tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.crt')
284
ca_file.write(ca_content)
285
ca_file.close()
286
ca_files.append(ca_file.name)
287
288
# Try to connect to each core in the group
289
for core in group_info.coreConnectivityInfoList:
290
print(f"Trying to connect to core: {core.coreThingArn}")
291
292
# Try each connectivity option for this core
293
for conn_info in core.connectivityInfoList:
294
try:
295
print(f"Attempting connection to {conn_info.host}:{conn_info.port}")
296
297
# Create MQTT client for this core
298
client = AWSIoTPyMQTT.AWSIoTMQTTClient("greengrassDevice")
299
client.configureEndpoint(conn_info.host, conn_info.port)
300
301
# Use the first CA file for this group
302
if ca_files:
303
client.configureCredentials(ca_files[0], "private.key", "certificate.crt")
304
305
# Configure connection parameters
306
client.configureConnectDisconnectTimeout(10)
307
client.configureMQTTOperationTimeout(5)
308
309
# Attempt connection
310
if client.connect():
311
print(f"Successfully connected to {conn_info.host}:{conn_info.port}")
312
313
# Test basic MQTT operations
314
client.publish("greengrass/test", f"Hello from {conn_info.host}", 0)
315
client.disconnect()
316
317
# Clean up CA files
318
for ca_file in ca_files:
319
os.unlink(ca_file)
320
321
# Connection successful, exit loops
322
exit()
323
324
except Exception as e:
325
print(f"Failed to connect to {conn_info.host}:{conn_info.port}: {e}")
326
continue
327
328
# Clean up CA files if no connection succeeded
329
for ca_file in ca_files:
330
os.unlink(ca_file)
331
```
332
333
### Advanced Discovery with Error Handling
334
335
```python
336
from AWSIoTPythonSDK.core.greengrass.discovery.providers import DiscoveryInfoProvider
337
from AWSIoTPythonSDK.exception.AWSIoTExceptions import (
338
DiscoveryTimeoutException,
339
DiscoveryUnauthorizedException,
340
DiscoveryDataNotFoundException,
341
DiscoveryThrottlingException,
342
DiscoveryFailure
343
)
344
import time
345
import json
346
347
def perform_discovery_with_retry(thing_name, max_retries=3, retry_delay=5):
348
"""Perform discovery with retry logic and comprehensive error handling"""
349
350
discoveryInfoProvider = DiscoveryInfoProvider()
351
discoveryInfoProvider.configureEndpoint("greengrass-ats.iot.region.amazonaws.com", 8443)
352
discoveryInfoProvider.configureCredentials("rootCA.crt", "certificate.crt", "private.key")
353
discoveryInfoProvider.configureTimeout(30)
354
355
for attempt in range(max_retries):
356
try:
357
print(f"Discovery attempt {attempt + 1}/{max_retries} for thing: {thing_name}")
358
359
discoveryInfo = discoveryInfoProvider.discover(thing_name)
360
361
# Validate discovery results
362
cores = discoveryInfo.getAllCores()
363
if not cores:
364
raise Exception("No Greengrass cores found in discovery response")
365
366
cas = discoveryInfo.getAllCas()
367
if not cas:
368
raise Exception("No CA certificates found in discovery response")
369
370
print(f"Discovery successful: {len(cores)} cores, {len(cas)} CAs")
371
return discoveryInfo
372
373
except DiscoveryTimeoutException:
374
print(f"Discovery timeout on attempt {attempt + 1}")
375
if attempt < max_retries - 1:
376
print(f"Retrying in {retry_delay} seconds...")
377
time.sleep(retry_delay)
378
379
except DiscoveryUnauthorizedException:
380
print("Discovery unauthorized - check credentials and thing permissions")
381
break # Don't retry auth failures
382
383
except DiscoveryDataNotFoundException:
384
print(f"No discovery data found for thing: {thing_name}")
385
print("Ensure thing is associated with a Greengrass group")
386
break # Don't retry data not found
387
388
except DiscoveryThrottlingException:
389
print("Discovery request throttled")
390
if attempt < max_retries - 1:
391
backoff_delay = retry_delay * (2 ** attempt) # Exponential backoff
392
print(f"Backing off for {backoff_delay} seconds...")
393
time.sleep(backoff_delay)
394
395
except DiscoveryFailure as e:
396
print(f"Discovery service failure: {e}")
397
if attempt < max_retries - 1:
398
print(f"Retrying in {retry_delay} seconds...")
399
time.sleep(retry_delay)
400
401
except Exception as e:
402
print(f"Unexpected discovery error: {e}")
403
if attempt < max_retries - 1:
404
print(f"Retrying in {retry_delay} seconds...")
405
time.sleep(retry_delay)
406
407
raise Exception(f"Discovery failed after {max_retries} attempts")
408
409
def analyze_discovery_results(discoveryInfo):
410
"""Analyze and display discovery results in detail"""
411
412
print("=== Discovery Results Analysis ===")
413
414
# Group-level analysis
415
groups = discoveryInfo.toObjectAtGroupLevel()
416
print(f"Found {len(groups)} Greengrass groups")
417
418
for group_id, group_info in groups.items():
419
print(f"\nGroup: {group_id}")
420
print(f" Cores: {len(group_info.coreConnectivityInfoList)}")
421
print(f" CA Certificates: {len(group_info.caList)}")
422
423
# Analyze each core
424
for i, core in enumerate(group_info.coreConnectivityInfoList):
425
print(f" Core {i+1}: {core.coreThingArn}")
426
print(f" Connectivity options: {len(core.connectivityInfoList)}")
427
428
# Analyze connectivity options
429
for j, conn_info in enumerate(core.connectivityInfoList):
430
print(f" Option {j+1}: {conn_info.host}:{conn_info.port}")
431
if conn_info.metadata:
432
print(f" Metadata: {json.dumps(conn_info.metadata, indent=8)}")
433
434
# Provide recommendations
435
print("\n=== Recommendations ===")
436
total_cores = len(discoveryInfo.getAllCores())
437
if total_cores > 1:
438
print("Multiple cores available - consider load balancing or failover")
439
elif total_cores == 1:
440
print("Single core available - ensure high availability setup")
441
else:
442
print("No cores found - check Greengrass group configuration")
443
444
# Example usage
445
try:
446
discovery_results = perform_discovery_with_retry("myIoTDevice")
447
analyze_discovery_results(discovery_results)
448
except Exception as e:
449
print(f"Discovery completely failed: {e}")
450
```
451
452
## Types
453
454
```python { .api }
455
# Discovery exception types
456
class DiscoveryTimeoutException(Exception):
457
"""Raised when discovery request times out"""
458
459
class DiscoveryUnauthorizedException(Exception):
460
"""Raised when discovery authentication fails"""
461
462
class DiscoveryDataNotFoundException(Exception):
463
"""Raised when no discovery data found for thing"""
464
465
class DiscoveryThrottlingException(Exception):
466
"""Raised when discovery requests are throttled"""
467
468
class DiscoveryFailure(Exception):
469
"""Raised for general discovery service failures"""
470
471
# Discovery result structure
472
discovery_response = {
473
"GGGroups": [
474
{
475
"GGGroupId": "group-12345",
476
"Cores": [
477
{
478
"thingArn": "arn:aws:iot:region:account:thing/core-thing",
479
"Connectivity": [
480
{
481
"Id": "connection-1",
482
"HostAddress": "192.168.1.100",
483
"PortNumber": 8883,
484
"Metadata": {
485
"network": "local"
486
}
487
}
488
]
489
}
490
],
491
"CAs": [
492
"-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
493
]
494
}
495
]
496
}
497
```