---
# System prepended metadata

title: Project report - Weather station on an iPad 2 with SMS alerts
tags: [Ipad 2, IoT, DHT-11, JS]

---

# Tutorial on how to build a weather station using your old iPad 2

*Nik Norman (nn222qy)*

The objective of this project is to repurpose an obsolete iPad to function as a weather station, utilizing a Raspberry Pi Pico equipped with temperature, humidity, and light sensors. The project is further enhanced by an SMS alert system designed to warn of potential fire or flood hazards. 

Depending on one's proficiency in server administration, the project replication is estimated to take approximately **2 hours**.

[TOC]

### Objective

The primary objective of this project is to repurpose an outdated iPad 2 by transforming it into a cutting-edge weather station. The weather station will encompass comprehensive features, including the ability to monitor indoor temperature and humidity levels. A key aspect of this endeavor is the incorporation of an alert system, which will promptly notify me via text message in the event of extreme temperature fluctuations.

This project serves two fundamental purposes. Firstly, it promotes sustainable consumption practices by repurposing an old electronic device that would otherwise be discarded or left unused. By breathing new life into the iPad 2, we contribute to minimizing electronic waste and extend the useful lifespan of the device.

Secondly, the weather station plays a crucial role in mitigating unforeseen circumstances, particularly in terms of fire prevention. The alert system serves as an early warning mechanism, allowing for timely intervention in situations where extreme temperature ranges could potentially lead to hazardous conditions. By receiving SMS notifications, appropriate actions can be taken promptly, preventing or minimizing the risk of fires or related incidents.

Through the integration of these dual objectives, this project not only showcases the potential of repurposing old devices but also contributes to enhancing safety measures in the face of unforeseen circumstances. By combining sustainability and proactive risk management, this weather station project provides an effective solution with a meaningful societal impact.

### Material

This project revolves around utilizing the Raspberry Pi Pico with WH modification as its foundational platform. The Raspberry Pi Pico with WH modification is an affordable device that offers WiFi connectivity, making it a suitable choice for this undertaking. Furthermore, it features a pre-soldered 40-pin header, which simplifies the process of connecting and integrating additional sensors and components.

To augment the functionality of the Raspberry Pi Pico  WH, a variety of sensors and components are employed. These are summarized in the table below:

| Product               | Image                                                                                        |    | Description                                                                                                                 |
|---------------------- |--------------------------------------------------------------------------------------------- |--- |---------------------------------------------------------------------------------------------------------------------------- |
| Raspberry Pi Pico WH  | ![PicoWH!](https://www.electrokit.com/uploads/productimage/41019/PICO-WH-HERO-1024x768.jpg)  | 1  | Raspberry Pi Pico WH boast an Infineon CYW43439 wireless chip which supports IEEE 802.11 b/g/n wireless LAN, and Bluetooth  |
| Breadboard 840        | ![Breadboard!](https://www.electrokit.com/uploads/productimage/10160/10160840.jpg)           | 1  | 840 Pi, 8.5mm, 8.5mm x 66mm                                                                                                 |
| DHT11                 | ![DHT11!](https://www.electrokit.com/uploads/productimage/41015/41015728-1-1024x768.jpg)     | 1  | Digital temperature and humidity sensor.                                                                                    |
| LED 1mm yellow        | ![Led!](https://www.electrokit.com/uploads/productimage/41000/5mm-gul-diffus.jpg)            | 1  | diffus 1500mcd                                                                                                              |
| Resistor              | ![Resistor!](https://www.electrokit.com/uploads/productimage/40810/40810233.png)             | 1  | 0.25W 330ohm (330R)                                                                                                         |
| Resistor              | ![Resistor!](https://www.electrokit.com/uploads/productimage/40810/40810410.png)             | 1  | 0.25W 10kohm (10k)                                                                                                          |
| Photo resistor        | ![Resistor!](https://www.electrokit.com/uploads/productimage/40850/40850001.jpg)             | 1  | CdS 4-7 kohm                                                                                                                |
| Jumpers wires         | ![Jumpers!](https://www.electrokit.com/uploads/productimage/41012/41012684-1024x804.jpg)     | 9  | Jumper wires 20-pin 30cm male/male. 20-pin jumper wire with connectors in both ends for use with breadboards and headers.   |
| Button                | ![Button!](https://www.electrokit.com/uploads/productimage/41016/41016089.jpg)               | 1  | 12x12mm                                                                                                                     |
| USB-kabel             | ![USBCab!](https://www.electrokit.com/uploads/productimage/41003/41003290.jpg)               | 1  | A-type – micro-B 5p type 1.8m                                                                                               |
|                       |                                                                                              |    | Total Price: 399 sek (Starter kit) + 19 sek (buttons)                                                                       |

By leveraging the capabilities of the Raspberry Pi Pico with WH modification and integrating the aforementioned sensors and components, this project aims to enhance its overall functionality and performance. The combination of these elements enables the project to achieve its objectives effectively and efficiently.


### Computer setup

To run a MicroPython project for Raspberry Pi Pico in PyCharm, you will need to follow several steps, including downloading and installing the IDE and configuring it to work with the Pico board. Additionally, you will need to flash the MicroPython firmware onto the Pico. Here is a detailed guide to help you through the process:

**1. Download and Install PyCharm:**
- Go to the JetBrains website (https://www.jetbrains.com/pycharm/) and download the appropriate version of PyCharm for your operating system.
- Run the installer and follow the on-screen instructions to complete the installation.

**2. Set up the Raspberry Pi Pico:**
- Connect your Raspberry Pi Pico to your computer using a USB cable.
- Make sure the Pico is in bootloader mode by pressing and holding the BOOTSEL button while connecting the USB cable.
- The Pico will appear as a removable storage device on your computer.

**3. Download and Install Thonny:**
- Thonny is a lightweight Python IDE that we will use to flash the MicroPython firmware onto the Pico.
- Go to the Thonny website (https://thonny.org/) and download the appropriate version for your operating system.
- Install Thonny by running the installer and following the on-screen instructions.

**4. Flash MicroPython Firmware:**
- Open Thonny IDE and select the correct interpreter for the Raspberry Pi Pico board. Go to Tools > Options > Interpreter, and choose the correct board (Raspberry Pi Pico) from the list.
- Click on the "Install or update firmware" button in the bottom-right corner of the Thonny window.
- Thonny will guide you through the process of downloading and flashing the MicroPython firmware onto the Pico. Follow the on-screen instructions and wait for the process to complete.

**5. Configure PyCharm:**
- Open PyCharm and create a new project by going to File > New Project.
- Select the project location and interpreter. Choose the interpreter by clicking on the gear icon next to the interpreter drop-down and selecting "Add..."
- In the Add Python Interpreter dialog, choose "System Interpreter" and browse to the MicroPython firmware you flashed onto the Pico. It should be located in the Pico's removable storage device.
- Click OK to save the interpreter settings.

**6. Write and Run the MicroPython Project:**
- Create a new Python file in your PyCharm project by right-clicking on the project folder and selecting New > Python File.
- Write your MicroPython code in the newly created file.
- To run the project on the Raspberry Pi Pico, you will need to configure the Run/Debug configuration in PyCharm. Click on the dropdown next to the green play button and choose "Edit Configurations..."
- In the Run/Debug Configurations dialog, click on the "+" button and select "MicroPython".
- In the MicroPython Configuration dialog, select the correct interpreter and specify the script file (the file containing your MicroPython code) in the "Script" field.
- Click OK to save the configuration.

**7. Run the MicroPython Project:**
- Connect the Raspberry Pi Pico to your computer via USB.
- Make sure the Pico is in the running mode (not bootloader mode).
- Click the green play button in PyCharm to run the project.
- PyCharm will upload the code to the Pico and run it. The output or results of your MicroPython project will be displayed in the PyCharm console.

By following these steps, you should be able to set up PyCharm to work with the Raspberry Pi Pico and run your MicroPython projects seamlessly.

The following steps are how to install your server and client side:

**8. Installing WebStorm**

- Visit the [JetBrains WebStorm website](https://www.jetbrains.com/webstorm/download/)
- Download the appropriate version for your operating system
- Follow the installation prompts and customize settings as desired
- Launch WebStorm after installation

**9. Creating a New Project**

- Open WebStorm
- Click "Create New Project" on the welcome screen
- Select "Node.js" and specify the project location
- Click "Create" and wait for the initialization

**10. Installing Node.js**

- Visit the [Node.js official website](https://nodejs.org/)
- Download the recommended LTS version for your operating system
- Run the installer and follow the on-screen instructions
- Verify the installation by opening a terminal and running `node -v`

**11. Initializing a Node.js Project**

- Open a terminal inside your WebStorm project folder
- Run `npm init` to create a package.json file
- Follow the prompts to set up your project details

**12. Installing Mongoose**

- Inside the terminal, run the following command to install Mongoose:

```
npm install mongoose
```


**13. Installing Axios**

- In the same terminal, run the following command to install Axios:

```
npm install axios
```


**14. Installing MongoDB**

- Visit the [MongoDB official website](https://www.mongodb.com/try/download/community)
- Download the Community Server version
- Run the installer and follow the on-screen instructions
- Verify the installation by running `mongod` in a terminal

**15. Connecting Mongoose to MongoDB**

- In your Node.js project, use the following code snippet to connect Mongoose to MongoDB:


```javascript=
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/your_database_name', { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => console.log('Connected to MongoDB'))
  .catch(err => console.error('Could not connect to MongoDB', err));
```


### Putting everything together

The project utilizes a circuit diagram, depicted in the accompanying figure, to illustrate the connections and components involved.

![](https://hackmd.io/_uploads/BJfxiM1Fh.png)


To facilitate the project, the Raspberry Pi Pico WH serves as the primary component. Additionally, several other components are integrated, including the DHT-11 digital temperature and humidity sensor, equipped with a built-in resistor. Furthermore, the project incorporates a button, a photoresistor (CdS) with a resistance range of 4-7 kΩ, an LED of the 5mm yellow diffuse type with a luminous intensity of 1500mcd (requiring a voltage of 2V and a current of 25mA), and supplementary resistors.

It is important to exercise caution when working with photoresistors and LEDs, as appropriate resistors need to be included in the circuit. Although the LED, specifically the 5mm yellow diffuse variant with a luminous intensity of 1500mcd, necessitates a 52Ω resistor, an alternative value of 330Ω was employed due to the unavailability of the exact resistor value. The resistor values were calculated using the formula: R = (V - Vf) / I, where V represents the power voltage, Vf denotes the LED voltage, and I signifies the LED current.

It is worth noting that certain instructions may not include resistors for the LED, but further investigation revealed that incorporating a resistor is still advisable.

![](https://hackmd.io/_uploads/B1gTA2GK3.jpg)

Moreover, the photoresistor necessitates a resistor value of approximately 11 kΩ to establish the desired voltage divider circuit. This value was determined utilizing the formula R = (Vcc * Rp) / (Rp - R), where Vcc represents the operating voltage of the Raspberry Pi Pico. This resistor plays a crucial role in enabling accurate measurement and control of the photoresistor.

By adhering to these considerations and calculations, the circuit is appropriately configured to support the components and ensure the smooth operation of the project.

### Platform

![](https://hackmd.io/_uploads/SyPyoofK3.png)

For this project, a cloud server provided by Hetzner.com is utilized. Specifically, a dedicated server running Ubuntu 18 is employed. The server configuration includes NGINX as the web server, along with Node.js for implementing the server-side functionality and MongoDB for database management. Additionally, the server hosts the static files required for the client-side portion of the project.

The setup and configuration process for this platform is intricate and comprehensive, and it is beyond the scope of this manual to provide detailed instructions. However, it is worth noting that alternative cloud solutions such as Amazon AWS, Digital Ocean, or even a personal home server can be viable alternatives. The choice of platform largely depends on the individual's familiarity and expertise in setting up servers, as well as prior experience with specific platforms.

While this project specifically utilizes a Hetzner, Node.js, and MongoDB, it is important to consider other options based on individual preferences, skill sets, and prior experience. This flexibility allows for adaptation to different server environments and ensures compatibility with various cloud providers or personal server setups.

### Note: Using a Local Computer for Development

If you are far from administering servers or you'd prefer to start development in a more controlled environment, you can use your local computer to check and run the project. This approach allows you to develop and test your code without the need for a remote server, making it a suitable choice for beginners and those who want to quickly prototype an application. Most of the tools and technologies mentioned above, such as WebStorm, Node.js, and MongoDB, are designed to work seamlessly on a local machine, providing you with a fully functional development environment right on your computer.


### The code

The Python script is designed to function as an environmental monitoring system for a residential setting, leveraging sensors linked to a Raspberry Pi Pico for the observation of temperature, humidity, and light conditions.

This script initiates by establishing a Wi-Fi connection using pre-configured credentials, followed by the initialization of a button, LED, and a suite of sensors. Furthermore, it arranges the necessary parameters for data transmission to a predetermined server.

The function named "button," operating on a timer basis, is designed to dispatch an SMS alert via Twilio if a specific button is actuated.

The main loop, operating in a perpetual manner, alternately reads sensor data and adjusts the LED state. The gathered data, comprising temperature, humidity, and light levels, is subsequently dispatched to a pre-established server in JSON format. If the measured temperature deviates from a prescribed range (10-30 degrees and less than 90 degrees), an SMS alert is issued via the Twilio API.

Post-data transmission, the server's response is printed to validate the successful execution of the operation. This loop executes at a frequency of every 10 seconds. To ensure robust performance, exception handling measures are incorporated to prevent potential script malfunction. An excerpt of the code snippet involved in server data transmission is illustrated below.

### Pico side

```python=
temp = sensor.temperature
humidity = sensor.humidity
print("Temperature: {}°C   Humidity: {:.0f}% ".format(temp, humidity))

light = photoRes.read_u16()
light = round(light / 65535 * 100, 2)

# define the data to send
data_homedata = '{"temperature": ' + str(temp) + ', "humidity": ' + str(humidity) + ', "light": ' + str(light) + '}'

# send the request
response = urequests.post(url_homedata, headers=headers_homedata, data=data_homedata)

# print the response
print(response.text)
response.close()
```

### Client side
```javascript=
function homeData() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', 'http://xxx.xxx.xxx.xxx:xxxx/api/homedata/data', true);
    xhr.onload = function() {
        if (xhr.status === 200) {
            var data = JSON.parse(xhr.responseText);
            console.log(data)
            
            document.getElementById('tempIn').innerHTML = data.temperature;
            document.getElementById('humidityIn').innerHTML = data.humidity;
            document.getElementById('light').innerHTML = data.light;
        } else {
            console.log('Error fetching data:', xhr.statusText);
            document.getElementById('goals').textContent = 'Error fetching data';
        }
    };

    xhr.onerror = function(event) {
        console.log('Request error');
        document.getElementById('goals').textContent = 'Request error';
    };

    xhr.send();
}
homeData()
setInterval(homeData, 10000);
```
### Server side
```javascript=
router.get('/data',
    async(req,res)=>{
        try {

            const goals = await analyticsData.getGoals()
            const visitors = await analyticsData.getVisitors()
]

            const temperature = await Record.findOne().sort({date: -1})
            console.log(temperature)
            console.log({goals, visitors, temperature: temperature.labels})
            return res.json({goals, visitors, temperature: temperature.labels.temperature, humidity: temperature.labels.humidity, light: temperature.labels.light})


        }catch (e) {
            console.log(e)
            res.send({message: "Server error"})
        }
    })

router.post('/add',
    async(req,res)=>{
        try {

            const {temperature, humidity, light} = req.body
            const record = new Record({labels:{temperature, humidity, light}})
            await record.save()
            console.log(req.body)
            return res.json({message: "Record added"})

        }catch (e) {
            console.log(e)
            res.send({message: "Server error"})
        }
    })
```

### Accessing the Complete Code

For the complete code and detailed examples related to this project, you can visit the GitHub repository at [https://github.com/NickZecamp/lnu-iot.git](https://github.com/NickZecamp/lnu-iot.git). Feel free to clone or download the repository to explore the code further.


### Transmitting the data / connectivity

The data collection process involves gathering information from various sensors and transmitting it to the designated endpoint in the form of JSON. The JSON structure consists of three key-value pairs: temperature, humidity, and light, with their corresponding values.

To establish the connection between the data source and the endpoint, a Wi-Fi connection is utilized. This connection is facilitated through a module present on the Raspberry Pi, which is connected to the local router. By leveraging this connection, the collected data can be transmitted reliably.

Data transmission occurs at regular intervals of 10 seconds, achieved through an HTTPS request. This frequency is deemed sufficient for the proper functioning of the weather station. However, alternative data protocols, such as MQTT or WebSocket, can be adopted if there is a requirement to send more data or monitor at higher frequencies.

These alternative protocols offer greater flexibility in terms of data transmission. MQTT (Message Queuing Telemetry Transport) is a lightweight messaging protocol that enables efficient communication between devices, allowing for the transfer of large volumes of data if necessary. On the other hand, WebSocket provides a full-duplex communication channel over a single TCP connection, allowing for real-time and bidirectional data exchange.

The choice of protocol depends on the specific needs of the weather station project. While the current implementation utilizes HTTPS for its suitability, the availability of alternative protocols ensures adaptability for scenarios that demand increased data transmission or more frequent monitoring.


### Presenting the data

The data presentation aspect of the project involves the creation of a customized dashboard using HTML, CSS, and Vanilla JavaScript. The source code for this dashboard can be obtained from the designated repository.

To populate the dashboard with data, an HTTP request is utilized to retrieve information from the server. The server, in turn, accesses the Mongo Database, which is a user-friendly and straightforward non-relational database capable of efficiently storing and retrieving JSON data. The server retrieves the relevant data and sends it as a JSON object.

![](https://hackmd.io/_uploads/B136a2MKn.png)

Subsequently, the received JSON data is parsed and dynamically inserted into the appropriate elements within the dashboard. This process occurs at regular intervals of 10 seconds, ensuring that the displayed data remains up-to-date.

![](https://hackmd.io/_uploads/SJDPgAMt2.png)


In line with the project's requirements, the implementation exclusively employs pure JavaScript, HTML, and CSS. These technologies were specifically chosen due to the limitations of the iPad 2, which lacks support for modern technologies and pre-packaged libraries. By leveraging these foundational technologies, the project maximizes compatibility with the iPad 2's capabilities while still providing an effective solution for data visualization and manipulation within the dashboard.


### Finalizing the design

{%youtube C35UOhs5-nY%}

The objective of this project is to rejuvenate an outdated iPad through the incorporation of Internet of Things (IoT) technologies. The undertaking presented numerous intriguing challenges that were successfully addressed, thereby establishing a deeper connection with this revitalized device. This device is anticipated to be an ongoing project, evolving through continuous use and development.



---
