Skip to content

Commit e57e4ce

Browse files
committed
update to latest pymongo aws lambda url functionality
1 parent bdae43e commit e57e4ce

File tree

1 file changed

+23
-77
lines changed

1 file changed

+23
-77
lines changed

docs/courses/hello-world/1.5-data-logging.md

+23-77
Original file line numberDiff line numberDiff line change
@@ -27,111 +27,54 @@ Chemistry and materials research data is precious. By making your data **F**inda
2727

2828
For storing our data, we will be using [MongoDB](https://www.mongodb.com/), a popular ["NoSQL"](https://www.mongodb.com/nosql-explained) database. It's important to note that MongoDB is just one of many excellent choices for databases (e.g., [PostgreSQL](https://www.postgresql.org/) for relational databases, which can be [hosted via AWS](https://aws.amazon.com/rds/postgresql/), and [Neo4j](https://neo4j.com/) for graph-based databases). MongoDB is a document-oriented database, which means it stores data in JSON-like documents. MongoDB is a popular choice for internet-of-things (IoT) applications due to its ease of setup, use, and scalability. Unfortunately, MongoDB Atlas suddenly deprecated their [Data API](https://docs.atlas.mongodb.com/data-api/) that allowed for direct reading and writing of data from devices like microcontrollers. Instead, we'll use something called AWS Lambda as an intermediary. AWS Lambda is a serverless compute service that lets you run code without provisioning or managing servers. It's a nice choice for creating lightweight APIs and handling intermittent requests, which works well for our microcontroller application.
2929

30-
For the purposes of this tutorial, we have set up a free-tier test database through MongoDB Atlas and an AWS Lambda function. We provide the necessary credentials which would normally be kept private. To prevent potential misuse from distributing a public API key (which is generally not a good practice), we have granted only write permissions for this tutorial, and the database is configured to automatically delete entries once a certain storage threshold is reached. The [companion notebook](./1.5.1-pymongo.ipynb) has a similar setup, where only read permissions are granted.
30+
For the purposes of this tutorial, we have set up a free-tier test database through MongoDB Atlas and an AWS Lambda function. We provide the necessary credentials which would normally be kept private. To prevent potential misuse from distributing a public API key (which is generally not a good practice), we have granted only write permissions for this tutorial, and the database is configured to automatically delete entries once a certain storage threshold is reached. The [companion notebook](./1.5.1-pymongo.ipynb) has a similar setup, where only read permissions are granted, which you will run later.
3131

32-
✅ Copy the following code into a new file on the microcontroller called `write_mongodb.py` and run the file. Note that you will need [`netman.py`](https://github.com/sparks-baird/self-driving-lab-demo/blob/main/src/public_mqtt_sdl_demo/lib/netman.py) [[permalink](https://github.com/sparks-baird/self-driving-lab-demo/blob/0ff0adec3e997c096990de594844d73a9ce18fd6/src/public_mqtt_sdl_demo/lib/netman.py)] and a file named `my_secrets.py` with your WiFi credentials, course ID, and Lambda function URL.
32+
✅ Copy the following code into a new file on the microcontroller called `write_mongodb.py` and run the file. Note that you will need [`netman.py`](https://github.com/sparks-baird/self-driving-lab-demo/blob/main/src/public_mqtt_sdl_demo/lib/netman.py) [[permalink](https://github.com/sparks-baird/self-driving-lab-demo/blob/0ff0adec3e997c096990de594844d73a9ce18fd6/src/public_mqtt_sdl_demo/lib/netman.py)] and a file named `my_secrets.py` with your WiFi credentials, course ID, and the Lambda function URL (see [[1](https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html)] and [[2](https://docs.aws.amazon.com/lambda/latest/dg/python-handler.html)]) you'll be using. For this tutorial, a function URL is provided for you. You will need to create your own for the assignment.
3333

3434
`my_secrets.py`
3535
```python
36-
36+
SSID = "Enter your SSID here"
37+
PASSWORD = "Enter your WiFi password here"
38+
COURSE_ID = "sassy-robin"
39+
ATLAS_URI = "https://bbwl4guz6jqors4xcnnll6sucq0ttapg.lambda-url.us-east-2.on.aws/"
3740
```
3841

39-
https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html
40-
https://medium.com/@g.bharthvajan/create-simple-get-post-rest-api-with-aws-lambda-function-url-7fa962197fa8
41-
42-
https://stackoverflow.com/questions/63310567/access-json-request-from-python-in-python-aws-lambda-function
43-
44-
https://docs.aws.amazon.com/lambda/latest/dg/python-handler.html
45-
4642
`write_mongodb.py`
4743
```python
48-
import requests
4944
import json
5045

51-
url = "https://p68yzl6gu6.execute-api.us-west-1.amazonaws.com/test/helloworld"
52-
53-
headers = {"course_id": "sassy-robin"}
54-
55-
response = requests.post(url, json=headers)
56-
57-
print(response.text)
58-
```
59-
60-
```python
61-
import json
62-
63-
64-
def lambda_handler(event, context):
65-
body = json.loads(event["body"])
66-
return {"statusCode": 200, "body": json.dumps(body)}
67-
```
68-
69-
70-
```python
71-
# based on https://medium.com/@johnlpage/introduction-to-microcontrollers-and-the-pi-pico-w-f7a2d9ad1394
46+
import requests
47+
from my_secrets import ATLAS_URI, COURSE_ID, PASSWORD, SSID
7248
from netman import connectWiFi
73-
import urequests
74-
75-
from my_secrets import SSID, PASSWORD, COURSE_ID
7649

7750
connectWiFi(SSID, PASSWORD, country="US")
7851

79-
DATA_API_KEY = "UT4cdinBetBaNqCBc5hISkaArhllv5dWfzXgbYsLYzpv79nqNhVwVsudQU5ZUmBE" # Public API key for demo purposes only
80-
CLUSTER_NAME = "test-cluster"
81-
DATABASE_NAME = "test-db"
82-
COLLECTION_NAME = "write-to-me"
83-
84-
ENDPOINT_BASE_URL = (
85-
"https://us-east-2.aws.data.mongodb-api.com/app/data-ibmqs/endpoint/data/v1"
86-
)
87-
88-
endpoint_url = f"{ENDPOINT_BASE_URL}/action/insertOne"
89-
90-
headers = {"api-key": DATA_API_KEY}
9152
document = {"course_id": COURSE_ID}
9253

93-
payload = {
94-
"dataSource": CLUSTER_NAME,
95-
"database": DATABASE_NAME,
96-
"collection": COLLECTION_NAME,
97-
"document": document,
98-
}
99-
100-
print(f"sending document to {CLUSTER_NAME}:{DATABASE_NAME}:{COLLECTION_NAME}")
101-
102-
num_retries = 3
103-
for _ in range(num_retries):
104-
response = urequests.post(endpoint_url, headers=headers, json=payload)
105-
txt = str(response.text)
106-
status_code = response.status_code
107-
108-
print(f"Response: ({status_code}), msg = {txt}")
54+
response = requests.post(ATLAS_URI, json=document)
10955

110-
response.close()
111-
112-
if status_code == 201:
113-
print("Added Successfully")
114-
break
115-
116-
print("Retrying...")
56+
if response.status_code == 200:
57+
response_data = response.json()
58+
print(response_data["message"])
59+
else:
60+
print(f"Request failed with status code {response.status_code}")
11761
```
11862

119-
The output should look something like the following (MAC address and IP address redacted, and your insertedId will be different):
63+
The output should look something like the following (MAC address and IP address redacted, and your ObjectID will be different):
12064

12165
> ```python
12266
> MAC address: ***
67+
> waiting for connection...
68+
> waiting for connection...
69+
> waiting for connection...
12370
> connected
12471
> ip = ***
125-
> sending document to test-cluster:test-db:write-to-me
126-
> Response: (201), msg = {"insertedId":"6594bfbfb3c925d2fdfbb7e8"}
127-
> Added Successfully
72+
> Document inserted successfully: {'course_id': 'free-squirrel', '_id': ObjectId('a1b2c3')}
12873
> ```
12974
13075
### Reading from MongoDB Using PyMongo
13176
132-
✅ Run the code from [the companion notebook](./1.5.1-pymongo.ipynb) to read data from a MongoDB database. Note that this also has a section about how to upload data via PyMongo (preferred when you're able to install PyMongo on e.g., a Raspberry Pi 5 or a Windows machine, which wasn't possible for the Pico W microcontroller).
133-
134-
<!-- ✅ Copy the following code into a new file called `read_mongodb.py` and run it on the microcontroller. -->
77+
✅ Run the code from [the companion notebook](./1.5.1-pymongo.ipynb) to read data from a MongoDB database. Note that this companion notebook also has a section about how to upload data via PyMongo (preferred when you're able to install PyMongo on e.g., a Raspberry Pi 5 or a Windows machine, which wasn't possible for the Pico W microcontroller). That way, you wouldn't need to use AWS Lambda as an intermediate layer.
13578
13679
### Reading Material
13780
@@ -150,6 +93,9 @@ The output should look something like the following (MAC address and IP address
15093
- [@sgbaird's list of materials databases](https://github.com/stars/sgbaird/lists/materials-databases)
15194
- Misc. [`awesome-materials-informatics`](https://github.com/tilde-lab/awesome-materials-informatics) (search for "database"), [`Materials-Databases` (no longer maintained)](https://github.com/blaiszik/Materials-Databases), [`awesome-chemistry-datasets`](https://github.com/kjappelbaum/awesome-chemistry-datasets)
15295
- [`awesome-self-driving-labs` research data management section](https://github.com/AccelerationConsortium/awesome-self-driving-labs#research-data-management)
96+
- [Create simple REST API (GET & POST method) with AWS Lambda Function URL](https://medium.com/@g.bharthvajan/create-simple-get-post-rest-api-with-aws-lambda-function-url-7fa962197fa8)
97+
- [Access json request from python in python AWS lambda function](https://stackoverflow.com/questions/63310567/access-json-request-from-python-in-python-aws-lambda-function)
98+
- [Insert Python Dictionary in PostgreSQL using Psycopg2](https://www.geeksforgeeks.org/insert-python-dictionary-in-postgresql-using-psycopg2/)
15399
154100
As a side note, MongoDB has a "serverless" option (i.e., pay only for what you use) that exceeds the free-tier limits and is more flexible than the shared and dedicated clusters, which may seem appealing at first. HOWEVER, [costs will escalate quickly if the database is not optimized](https://www.mongodb.com/developer/products/atlas/serverless-instances-billing-optimize-bill-indexing/) (e.g., the database is not indexed). If you decide to go with MongoDB Atlas for a project and need more than the 512 MB of free-tier storage, we recommend first considering the shared (e.g., M2, M5) and dedicated options, hosting your own MongoDB instance, or looking to other ecosystems. Beware of serverless. Looking to other ecosystems could be either a full replacement or a supplement (e.g., using AWS for storing large files and adding links to those files into MongoDB).
155101

0 commit comments

Comments
 (0)