# Welcome to the QuantAQ Docs!

Welcome to the QuantAQ Docs site. The QuantAQ Docs are a great place to learn about and explore our hardware, software, and developer tools, and to find the information you need about our professional-grade air quality sensors.

## Jump right in

### Hardware

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>MODULAIR</strong></td><td>PM + Gas Sensor</td><td></td><td></td><td><a href="/pages/Zvukm7MAGL6ooitMTmpY">/pages/Zvukm7MAGL6ooitMTmpY</a></td></tr><tr><td><strong>MODULAIR-PM</strong></td><td>PM Sensor</td><td></td><td></td><td><a href="/pages/JjjojIyKxaiBPzzLwvtg">/pages/JjjojIyKxaiBPzzLwvtg</a></td></tr><tr><td>MODULAIR-UFP</td><td>Ultrafine Particle Monitor</td><td></td><td></td><td><a href="/pages/qdzBtdXXWN0LaFBJ0FLD">/pages/qdzBtdXXWN0LaFBJ0FLD</a></td></tr><tr><td><strong>Solar Power System</strong></td><td>Make your life easier with our easy-to-use tooling.</td><td></td><td></td><td><a href="/pages/UDhKdp21j7FELbEmPlLJ">/pages/UDhKdp21j7FELbEmPlLJ</a></td></tr></tbody></table>

### Software

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>QuantAQ Cloud API</strong></td><td>Learn the basics of the QuantAQ Cloud API.</td><td></td><td><a href="/pages/bnoHXM0uKbmlKoJcpIu9">/pages/bnoHXM0uKbmlKoJcpIu9</a></td></tr><tr><td><strong>Developer Tools &#x26; Resources</strong></td><td>Make your life easier with our easy-to-use tooling.</td><td></td><td><a href="/pages/NJurpJLFFvrUhc8aAk4K">/pages/NJurpJLFFvrUhc8aAk4K</a></td></tr></tbody></table>


# MODULAIR

In April 2025, QuantAQ began shipping new MODULAIR systems that are slightly different than previous versions. Newer MODULAIR systems have serial numbers that begin with **"MOD-X"** and start at serial number MOD-X-00890. If your serial number is lower than 890 a*nd* the serial number starts with **"MOD-",** please use the product manual for the original MODULAIR.

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>MODULAIR</td><td>Original QuantAQ MODULAIR systems with serial numbers below 890.</td><td><a href="/pages/CyH2xJQs9yWJ1S8BYNav">/pages/CyH2xJQs9yWJ1S8BYNav</a></td></tr><tr><td>MODULAIR-X</td><td>New QuantAQ MODULAIR systems (2025) with serial numbers above 890.</td><td><a href="/pages/ZbKxvh9JdeDjchW2DcMC">/pages/ZbKxvh9JdeDjchW2DcMC</a></td></tr></tbody></table>


# MODULAIR (pre-2025)dhh

This page documents the QuantAQ MODULAIR air quality sensor.

| KEY              | VALUE                                                                             |                                                                    |
| ---------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| **Product Name** | MODULAIR                                                                          |                                                                    |
| **SKU(s)**       | MOD-XXX-NorAm                                                                     | Pre-2025 version of the MODULAIR for use in North America.         |
|                  | MOD-XXX-Global                                                                    | Pre-2025 version of the MODULAIR for use outside of North America. |
| **Datasheet**    | [Download](https://assets.quant-aq.com/downloads/spec-sheets/modulair.latest.pdf) |                                                                    |

{% hint style="info" %}
XXX is a 3-digit number that indicates the gas sensors included in a specific sensor. The available options historically have been:

1. 000: PM only
2. 015: PM, CO, NO, NO2, O3
3. 031: PM, CO, NO, NO2, O3, CO2

Only the 000 and 015 have been manufactured and sold since 2023.
{% endhint %}

## 1. Introduction and Specs

MODULAIR™ provides real-time estimates of particulate matter concentrations (PM1, PM2.5, PM10), the particle size distribution, and four gas-phase measurements. MODULAIR utilizes the same, patent-pending particle measurement technology found in the MODULAIR-PM, which combines nephelometry with single-particle scattering to accurately measure aerosol loadings across a variety of environments.

### 1.1. Specifications

#### 1.1.1 Air Quality Measurements

| PARAMETER                  | RANGE                     | ACCURACY                   |
| -------------------------- | ------------------------- | -------------------------- |
| PM1, PM2.5, PM10           | 0 to 2,000 µg/m3          | Please see the spec sheet. |
| Particle size distribution | 0.35 to 40.0 µm (24 bins) | Not yet determined         |
| Ozone (O3)                 | 0 to 500 ppb              | 5 ppb or 20%               |
| Carbon Monoxide (CO)       | 0 to 13,000 ppb           | 40 ppb or 20%              |
| Nitrogen Oxide (NO)        | 0 to 5,000 ppb            | 5 ppb or 20%               |
| Nitrogen Dioxide (NO2)     | 0 to 5,000 ppb            | 6 ppb or 35%               |
| Temperature\*              | -40º to 85º C             | +/- 0.2ºC                  |
| Relative Humidity\*        | 0 to 100%                 | +/- 2%                     |

*\*Temperature and relative humidity are measured inside the flow cell and should not be interpreted as true ambient measurements.*

For more information on the operating principle and performance of the MODULAIR, please refer to [QAN-001](https://zenodo.org/records/10688216), [QAN-003](https://zenodo.org/records/11200301), and [QAN-004](https://zenodo.org/records/14456513).

#### 1.1.2 Power and Communications

<table><thead><tr><th width="254">PARAMETER</th><th>DETAILS</th></tr></thead><tbody><tr><td>🔋 <strong>Power</strong></td><td>5V, 2A (supply)<br>250 mA average consumption</td></tr><tr><td>🗼 <strong>Communication</strong></td><td>LTE CAT-M1 (North America)<br>LTE CAT-M1/3G/2G (Global)</td></tr><tr><td>📈 <strong>Data</strong></td><td>Web interface (quant-aq.com)<br>Programmatic access (QuantAQ API)<br>Local storage (µSD Card)</td></tr></tbody></table>

#### 1.1.3 Operating Specifications

| PARAMETER             | DETAILS                  |
| --------------------- | ------------------------ |
| Weatherproof rating   | IP68                     |
| Operating temperature | -20º to 45ºC             |
| Operating humidity    | 5 to 95%, non-condensing |
| Dimensions            | 11.04" x 9.04" x 5.72"   |
| Weight                | 6 lbs (2.72 kg)          |

### 1.2 Certifications

#### 1.2.1 FCC 15(b)

The MODULAIR™ air quality sensor complies with part 15 of the FCC rules for class A devices. Operation is subject to the following two conditions: (1) this device may not cause harmful interference; (2) this device must accept any interference received, including interference that may cause undesired operation.

<figure><img src="/files/A6w12CqSltBWoXsVOPGl" alt="" width="188"><figcaption></figcaption></figure>

**Model:** MODULAIR

**Contains FCC ID**: 2AEMI-B404X

#### 1.2.2 CE

The MODULAIR™ complies with European Union EMC Directive 2014/30/EU and conforms to the following technical standards (EN 55011, EN 61326).

<figure><img src="/files/hlfLadE4Z8eX0Tlmpnqr" alt="" width="188"><figcaption></figcaption></figure>

**Model:** MODULAIR

**Contains FCC ID**: 2AEMI-B524

## 2. Installation and Hardware Setup

### 2.1 Unpacking

When you unpack your MODULAIR, you should have received the following:

* MODULAIR Air Quality Sensor
* Power supply and USB-C charging cable
* Mounting hardware (flanges with 4, 10-32 screws)
* 16 GB µSD card (pre-installed)
* Device registration card
* Sonic anemometer (if purchased)
* Solar Power System (if purchased)

If any of these components are missing, please contact QuantAQ support via the in-app chat.

#### 2.2.1 Device Overview

Upon opening your MODULAIR, it should appear as Figure 2.1 shows below, without the antenna attached. When attached, the antenna should be facing *up* to get the best service.

<figure><img src="/files/rSZiBAn7e5403VwEeC1Z" alt=""><figcaption><p>Figure 2.1: A top-down view of the MODULAIR.</p></figcaption></figure>

#### 2.2.2 Device Front Panel

The front panel of the MODULAIR can be accessed by opening the lid of the enclosure. The panel provides access to the *ON/OFF* switch, the µSD card for local data logging, the internal battery status indicator (*Battery Charge Status*), and the device status LED (*Device Status Indicator*), all of which are shown in Figure 2.2.

**Front Panel Screw**

The front panel can be opened by unscrewing the *Front Panel Screw*, though should not be necessary under normal use. If it is opened, make sure that when re-closing, you do not "pop" out the µSD card. If so, you can simply push it back into place.

<figure><img src="/files/x9LY5rrSnMJxhrO6uJDb" alt=""><figcaption><p>Figure 2.2: The internal front-panel of the MODULAIR.</p></figcaption></figure>

#### 2.2.3 Device Base

Viewing the bottom of the MODULAIR, you can see the air intake covered by an insect-screen, the RJ11 jack for connecting the optional sonic anemometer, and the USB-C power in.

<figure><img src="/files/ZITFn1rVTgVg9bIXmiFi" alt=""><figcaption><p>Figure 2.3: The MODULAIR bottom view depicting the air intake, power cable connection (USB-C), and aneometer hook up.</p></figcaption></figure>

#### 2.2.4 Device Circuit Board

The device circuit board is located under the front panel (Figure 2.2). To access, un-screw the *Front Panel Screw* and you will see the Core Board toward the lower left, as shown in Figure 2.4. The micro-USB cable is used exclusively for streaming logs directly from the device. While it does output some data, it is not designed to be used to connect to a data logger (this behavior is not supported). When used to collect logs, the MODULAIR must still be powered by the normal Power In USB-C connector shown in Figure 2.3.

<figure><img src="/files/0i8irAXeEaaAbU7q8Dp0" alt=""><figcaption><p>Figure 2.4: Internally, the micro-USB connector for streaming logs can be found under the front panel.</p></figcaption></figure>

### 2.3 Connections and Device Registration

The MODULAIR is shipped completely assembled, aside from the mounting hardware. Once the device is mounted and you have verified the power switch is in the OFF position, plug in the power supply and connect the USB-C cable to the bottom of the device. Once the power cable is connected, flip the power switch to the **ON** position. Upon receiving power, the Device Status LED (Figure 2.2) will flash green and eventually begin a sequence of slowly breathing cyan; this indicates the cellular connection is active and a session with the cloud server has begun.

{% hint style="info" %}
If the device is being powered on in a new location or has been powered off for an extended period of time, this may take some time to complete.
{% endhint %}

The device will log data locally during the period where it is searching for cellular service and push the data to the server once a connection is established. If the LED indicator does not eventually begin breathing cyan, this indicates a cloud connectivity problem. Common errors and next steps can be found in Section 6.2.

To register your device, scan the QR code on the device registration card you received with your device. It is easiest to complete this step using a cellphone or tablet with a working internet connection. A laptop with a functioning camera will also work, though may be more difficult. It is also suggested that you first log in to the website (quant-aq.com) on the device you will use to complete this process. To register your device:

1. Use your camera to scan the QR code. This will open a tab in your default browser and will direct you to the device registration page.
2. Enter the fields for the information that the form asks for and click "Continue"
3. Enter the claim code found on the same QR code card → it should be a 6-character alphanumeric code.
4. Follow the instructions on the form and enter in data for the device location and other meta data. All of these can be changed in the future through the dashboard, so don't worry if you can't answer all questions at this time.

### 2.4 Installation

The MODULAIR can be mounted in several ways, depending on your exact use and the available mounting options available to you. The device is shipped with mounting flanges, which can be used to easily mount the device to several surfaces. Each flange is secured to the back of the device with two 10-32 stainless steel screws (included). Each flange includes three slots with the following dimensions:

<figure><img src="/files/JYPr01AChbmabqITpBST" alt=""><figcaption><p>Figure 2.5: Domensions of the mounting holes for the provided mounting flanges.</p></figcaption></figure>

Common installation approaches include:

* using high-strength zip ties to secure the device to a fence or post (not recommended)
* using screws to mount the device to a wall using the provided flanges
* Using u-bolts or similar to attach to a fence post, fence, or rail
* Purchase a pole mount kit from Polycase (the box supplier). [Polycase part number PK-087](https://www.polycase.com/pk-087).

The complete box dimensions are:

11.04" x 9.04" x 5.72" (280.42 x 229.62 x 145.29 mm)

### 2.5 Connectivity Considerations

As all QuantAQ products are internet-connected, it is important to consider connectivity when choosing an installation location. There are three primary things to consider:

1. **Antenna Connection.** If your device has an external antenna, ensure it is seated securely and placed at a 90º angle pointing toward the sky.
2. **Antenna Placement.** Do not place the device near metal objects or other sources of RF (i.e., antenna). Keep the antenna at least 18" away from metal objects as they can cause distortions and reflections.
3. **Location and Cellular Availability.** Install your sensor in a location with a known cellular signal on the carriers we support.

## 3. Software Setup and Data

### 3.1 Data Structure and Outputs

There are three primary ways in which data can be accessed for the MODULAIR:

1. Raw data is stored locally on the µSD card
2. Data can be downloaded from the QuantAQ Cloud Console
3. Data can be downloaded from the QuantAQ API

The data formats are slightly different depending on which method you’ve used to access the data, each of which is documented below.

#### 3.1.1 Data Stored Locally on the µSD Card

Data is collected and saved to an onboard µSD card every five seconds; each minute, these values are averaged and pushed to the cloud where they are available on the QuantAQ Cloud. It is unlikely you will ever *need* to use the locally saved data; however, you are more than welcome to use it if you would like. This section covers the locally stored data and how to understand it. When removing the µSD card to pull the data, make sure your device is turned OFF.

On the µSD card, you will find data files (with a prefix of DATA\_YYYYMMDD.csv) and log files which are located in the logs directory. Log files contain debugging information about the onboard sensors and the cellular communication module. It is unlikely these logs will be useful to most users, though they are available to you if you would like to use them. It is highly recommended that you use the QuantAQ CLI (discussed below) to analyze them, as it will vastly reduce the amount of time needed.

<figure><img src="/files/n88Jwhpri8BbEbfcn5fo" alt=""><figcaption><p>Figure 3.1: Sample of a data file header. The first three rows include meta data with the following rows containined the header and data.</p></figcaption></figure>

Data files are written each day and can be read or analyzed using any programming language or spreadsheet program (e.g., Microsoft Excel). Each file begins with three meta-data rows describing the device model (row 1), device ID (row 2), and device serial number (row 3). See Figure 3.1A below. If you are automating your data analysis, you can skip these three rows. The fourth row contains the header information with the names of all columns. The remaining rows contain the data, where each row corresponds to a new 5-second sampling interval. The table below summarizes the columns.

The data outputs will change depending on the SKU (or model) of your MODULAIR. Most columns are constant except for the gas-phase columns.

<table><thead><tr><th width="196">COLUMN</th><th width="96">SKU</th><th width="126">UNIT</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>timestamp_iso</td><td>all</td><td></td><td>The sample timestamp in ISO format</td></tr><tr><td>sku</td><td>all</td><td></td><td>The device SKU number</td></tr><tr><td>fw</td><td>all</td><td></td><td>The current firmware version</td></tr><tr><td>flag</td><td>all</td><td></td><td>The status flag corresponding to this data row</td></tr><tr><td>sample_temp</td><td>all</td><td>°C</td><td>The sample temperature</td></tr><tr><td>sample_rh</td><td>all</td><td>%</td><td>The sample relative humidity</td></tr><tr><td>bin0</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin0 (0.35 - 0.46 µm)</td></tr><tr><td>bin1</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin1 (0.46 - 0.66 µm)</td></tr><tr><td>bin2</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin2 (0.66 - 1.0 µm)</td></tr><tr><td>bin3</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin3 (1.0 - 1.3 µm)</td></tr><tr><td>bin4</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin4 (1.3 - 1.7 µm)</td></tr><tr><td>bin5</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin5 (1.7 - 2.3 µm)</td></tr><tr><td>bin6</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin6 (2.3 - 3.0 µm)</td></tr><tr><td>bin7</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin7 (3.0 - 4.0 µm)</td></tr><tr><td>bin8</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin8 (4.0 - 5.2 µm)</td></tr><tr><td>bin9</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin9 (5.2 - 6.5 µm)</td></tr><tr><td>bin10</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin10 (6.5 - 8.0 µm)</td></tr><tr><td>bin11</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin11 (8.0 - 10.0 µm)</td></tr><tr><td>bin12</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin12 (10.0 - 12.0 µm)</td></tr><tr><td>bin13</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin13 (12.0 - 14.0 µm)</td></tr><tr><td>bin14</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin14 (14.0 - 16.0 µm)</td></tr><tr><td>bin15</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin15 (16.0 - 18.0 µm)</td></tr><tr><td>bin16</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin16 (18.0 - 20.0 µm)</td></tr><tr><td>bin17</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin17 (20.0 - 22.0 µm)</td></tr><tr><td>bin18</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin18 (22.0 - 25.0 µm)</td></tr><tr><td>bin19</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin19 (25.0 - 28.0 µm)</td></tr><tr><td>bin20</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin20 (28.0 - 31.0 µm)</td></tr><tr><td>bin21</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin21 (31.0 - 34.0 µm)</td></tr><tr><td>bin22</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin22 (34.0 - 37.0 µm)</td></tr><tr><td>bin23</td><td>all</td><td>p/cm3</td><td>Number of particles per cubic cm in bin23 (37.0 - 40.0 µm)</td></tr><tr><td>bin1MToF</td><td>all</td><td>ml/s</td><td>Time of flight for particles in bin1</td></tr><tr><td>bin3MToF</td><td>all</td><td>ml/s</td><td>Time of flight for particles in bin3</td></tr><tr><td>bin5MToF</td><td>all</td><td>ml/s</td><td>Time of flight for particles in bin5</td></tr><tr><td>bin7MToF</td><td>all</td><td>ml/s</td><td>Time of flight for particles in bin7</td></tr><tr><td>sample_period</td><td>all</td><td>s</td><td>The sample period in seconds.</td></tr><tr><td>sample_flow</td><td>all</td><td>ml/s</td><td>The OPC sample flow rate.</td></tr><tr><td>opc_temp</td><td>all</td><td>°C</td><td>The internal temperature of the OPC</td></tr><tr><td>opc_rh</td><td>all</td><td>%</td><td>The internal relative humidity of the OPC</td></tr><tr><td>opc_pm1</td><td>all</td><td>µg/m3</td><td>The factory computed value for PM1 from the OPC</td></tr><tr><td>opc_pm25</td><td>all</td><td>µg/m3</td><td>The factory computed value for PM2.5 from the OPC</td></tr><tr><td>opc_pm10</td><td>all</td><td>µg/m3</td><td>The factory computed value for PM10 from the OPC</td></tr><tr><td>laser_status</td><td>all</td><td></td><td>The status of the OPC laser.</td></tr><tr><td>pm1_std</td><td>all</td><td>µg/m3</td><td>The factory computed value for PM1 from the Nephelometer</td></tr><tr><td>pm25_std</td><td>all</td><td>µg/m3</td><td>The factory computed value for PM2.5 from the Nephelometer</td></tr><tr><td>pm10_std</td><td>all</td><td>µg/m3</td><td>The factory computed value for PM10 from the Nephelometer</td></tr><tr><td>pm1_env</td><td>all</td><td>µg/m3</td><td>The factory computed value for PM1 from the Nephelometer</td></tr><tr><td>pm25_env</td><td>all</td><td>µg/m3</td><td>The factory computed value for PM2.5 from the Nephelometer</td></tr><tr><td>pm10_env</td><td>all</td><td>µg/m3</td><td>The factory computed value for PM10 from the Nephelometer</td></tr><tr><td>neph_bin0</td><td>all</td><td>p</td><td>Number of particles in bin0 for the nephelometer</td></tr><tr><td>neph_bin1</td><td>all</td><td>p</td><td>Number of particles in bin1 for the nephelometer</td></tr><tr><td>neph_bin2</td><td>all</td><td>p</td><td>Number of particles in bin2 for the nephelometer</td></tr><tr><td>neph_bin3</td><td>all</td><td>p</td><td>Number of particles in bin3 for the nephelometer</td></tr><tr><td>neph_bin4</td><td>all</td><td>p</td><td>Number of particles in bin4 for the nephelometer</td></tr><tr><td>neph_bin5</td><td>all</td><td>p</td><td>Number of particles in bin5 for the nephelometer</td></tr><tr><td>ws</td><td>all</td><td>mph</td><td>The wind speed from the sonic anemometer.</td></tr><tr><td>wd</td><td>all</td><td>deg</td><td>The wind direction from the sonic anemometer.</td></tr><tr><td>co_we</td><td>015, 031, 033</td><td>mV</td><td>The working electrode signal for the CO sensor.</td></tr><tr><td>co_ae</td><td>015, 031, 033</td><td>mV</td><td>The auxiliary electrode signal for the CO sensor.</td></tr><tr><td>no_we</td><td>015, 031</td><td>mV</td><td>The working electrode signal for the NO sensor.</td></tr><tr><td>no_ae</td><td>015, 031</td><td>mV</td><td>The auxiliary electrode signal for the NO sensor.</td></tr><tr><td>so2_we</td><td>033</td><td>mV</td><td>The working electrode signal for the SO2 sensor.</td></tr><tr><td>so2_ae</td><td>033</td><td>mV</td><td>The auxiliary electrode signal for the SO2 sensor.</td></tr><tr><td>no2_we</td><td>015, 031</td><td>mV</td><td>The working electrode signal for the NO2 sensor.</td></tr><tr><td>no2_ae</td><td>015, 031</td><td>mV</td><td>The auxiliary electrode signal for the NO2 sensor.</td></tr><tr><td>ox_we</td><td>015, 031</td><td>mV</td><td>The working electrode signal for the OX sensor.</td></tr><tr><td>ox_ae</td><td>015, 031</td><td>mV</td><td>The auxiliary electrode signal for the OX sensor.</td></tr><tr><td>co2_raw</td><td>031</td><td>mV</td><td>The raw signal for the CO2 sensor.</td></tr></tbody></table>

#### 3.1.2 Data Downloaded from the QuantAQ Cloud Console

Data are pushed to the QuantAQ Cloud with 1-minute time resolution and can be downloaded via the QuantAQ Cloud Console. When downloading data, you can select whether you would like to download the *raw* data, the *final* data, or both the *raw+final* data. Generally, the *final* data is what is desired, as it contains the final, cleaned data that is ready for analysis. The *raw* data is well-suited for researchers trying to investigate specific questions. When downloaded, the data is exported as a csv and contains the following columns:

<table><thead><tr><th width="175">COLUMN</th><th width="163">FILE LOCATION<select multiple><option value="5slOPqU2kxUP" label="raw" color="blue"></option><option value="sMTBc5UWaamS" label="final" color="blue"></option></select></th><th width="90">UNITS</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>timestamp</td><td><span data-option="5slOPqU2kxUP">raw, </span><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>The sample timestamp in ISO format</td></tr><tr><td>id</td><td><span data-option="5slOPqU2kxUP">raw, </span><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>A unique id the corresponds to the record shown</td></tr><tr><td>timestamp_local</td><td><span data-option="5slOPqU2kxUP">raw, </span><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>The sample timestamp in ISO format, corrected for the timezone as defined in the device settings</td></tr><tr><td>sn</td><td><span data-option="5slOPqU2kxUP">raw, </span><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>The device serial number</td></tr><tr><td>rh</td><td><span data-option="5slOPqU2kxUP">raw, </span><span data-option="sMTBc5UWaamS">final</span></td><td>%</td><td>The sample relative humidity</td></tr><tr><td>temp</td><td><span data-option="5slOPqU2kxUP">raw, </span><span data-option="sMTBc5UWaamS">final</span></td><td>°C</td><td>The sample temperature</td></tr><tr><td>bin0</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin0 (0.35 - 0.46 µm)</td></tr><tr><td>bin1</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin1 (0.46 - 0.66 µm)</td></tr><tr><td>bin2</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin2 (0.66 - 1.0 µm)</td></tr><tr><td>bin3</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin3 (1.0 - 1.3 µm)</td></tr><tr><td>bin4</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin4 (1.3 - 1.7 µm)</td></tr><tr><td>bin5</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin5 (1.7 - 2.3 µm)</td></tr><tr><td>bin6</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin6 (2.3 - 3.0 µm)</td></tr><tr><td>bin7</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin7 (3.0 - 4.0 µm)</td></tr><tr><td>bin8</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin8 (4.0 - 5.2 µm)</td></tr><tr><td>bin9</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin9 (5.2 - 6.5 µm)</td></tr><tr><td>bin10</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin10 (6.5 - 8.0 µm)</td></tr><tr><td>bin11</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin11 (8.0 - 10.0 µm)</td></tr><tr><td>bin12</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin12 (10.0 - 12.0 µm)</td></tr><tr><td>bin13</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin13 (12.0 - 14.0 µm)</td></tr><tr><td>bin14</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin14 (14.0 - 16.0 µm)</td></tr><tr><td>bin15</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin15 (16.0 - 18.0 µm)</td></tr><tr><td>bin16</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin16 (18.0 - 20.0 µm)</td></tr><tr><td>bin17</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin17 (20.0 - 22.0 µm)</td></tr><tr><td>bin18</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin18 (22.0 - 25.0 µm)</td></tr><tr><td>bin19</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin19 (25.0 - 28.0 µm)</td></tr><tr><td>bin20</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin20 (28.0 - 31.0 µm)</td></tr><tr><td>bin21</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin21 (31.0 - 34.0 µm)</td></tr><tr><td>bin22</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin22 (34.0 - 37.0 µm)</td></tr><tr><td>bin23</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin23 (37.0 - 40.0 µm)</td></tr><tr><td>opcn3_pm1</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>µg/m3</td><td>Factory computed value of PM1 from the OPC</td></tr><tr><td>opcn3_pm25</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>µg/m3</td><td>Factory computed value of PM2.5 from the OPC</td></tr><tr><td>opcn3_pm10</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>µg/m3</td><td>Factory computed value of PM10 from the OPC</td></tr><tr><td>pm1_env</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>µg/m3</td><td>Factory computed value of PM1 from the nephelometer</td></tr><tr><td>pm25_env</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>µg/m3</td><td>Factory computed value of PM2.5 from the nephelometer</td></tr><tr><td>pm10_env</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>µg/m3</td><td>Factory computed value of PM10 from the nephelometer</td></tr><tr><td>neph_bin0</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>p</td><td>The number of particles in bin0 from the nephelometer</td></tr><tr><td>wd</td><td><span data-option="5slOPqU2kxUP">raw, </span><span data-option="sMTBc5UWaamS">final</span></td><td>deg</td><td>Wind direction from the sonic anemometer</td></tr><tr><td>ws</td><td><span data-option="5slOPqU2kxUP">raw, </span><span data-option="sMTBc5UWaamS">final</span></td><td>mph</td><td>Wind speed from the sonic anemometer</td></tr><tr><td>co_we</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The working electrode signal for the CO sensor.</td></tr><tr><td>co_ae</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The auxiliary electrode signal for the CO sensor.</td></tr><tr><td>no_we</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The working electrode signal for the NO sensor.</td></tr><tr><td>no_ae</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The auxiliary electrode signal for the NO sensor.</td></tr><tr><td>no2_we</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The working electrode signal for the NO2 sensor.</td></tr><tr><td>no2_ae</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The auxiliary electrode signal for the NO2 sensor.</td></tr><tr><td>o3_we</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The working electrode signal for the O3 sensor.</td></tr><tr><td>o3_ae</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The auxiliary electrode signal for the O3 sensor.</td></tr><tr><td>co2_raw</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The raw CO2 signal</td></tr><tr><td>co_diff</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The difference between co_we and co_ae</td></tr><tr><td>no_diff</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The difference between no_we and no_ae</td></tr><tr><td>no2_diff</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The difference between no2_we and no2_ae</td></tr><tr><td>ox_diff</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td>mV</td><td>The difference between o3_we and o3_ae</td></tr><tr><td>flag</td><td><span data-option="5slOPqU2kxUP">raw</span></td><td></td><td>The status flag corresponding to this record</td></tr><tr><td>lat</td><td><span data-option="5slOPqU2kxUP">raw, </span><span data-option="sMTBc5UWaamS">final</span></td><td>deg</td><td>The latitude of the device</td></tr><tr><td>lon</td><td><span data-option="5slOPqU2kxUP">raw, </span><span data-option="sMTBc5UWaamS">final</span></td><td>deg</td><td>The longitude of the device</td></tr><tr><td>device_state</td><td><span data-option="5slOPqU2kxUP">raw, </span><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>The current state of the device</td></tr><tr><td>pm1</td><td><span data-option="sMTBc5UWaamS">final</span></td><td>µg/m3</td><td>The PM1 value</td></tr><tr><td>pm25</td><td><span data-option="sMTBc5UWaamS">final</span></td><td>µg/m3</td><td>The PM2.5 value</td></tr><tr><td>pm10</td><td><span data-option="sMTBc5UWaamS">final</span></td><td>µg/m3</td><td>The PM10 value</td></tr><tr><td>co</td><td><span data-option="sMTBc5UWaamS">final</span></td><td>ppb</td><td>The CO concentration</td></tr><tr><td>no</td><td><span data-option="sMTBc5UWaamS">final</span></td><td>ppb</td><td>The NO concentration</td></tr><tr><td>no2</td><td><span data-option="sMTBc5UWaamS">final</span></td><td>ppb</td><td>The NO2 concentration</td></tr><tr><td>o3</td><td><span data-option="sMTBc5UWaamS">final</span></td><td>ppb</td><td>The O3 concentration</td></tr><tr><td>co2</td><td><span data-option="sMTBc5UWaamS">final</span></td><td>ppm</td><td>The CO2 concentration</td></tr><tr><td>pm1_model_id</td><td><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>The id corresponding to the model used to compute PM1</td></tr><tr><td>pm25_model_id</td><td><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>The id corresponding to the model used to compute PM2.5</td></tr><tr><td>pm10_model_id</td><td><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>The id corresponding to the model used to compute PM10</td></tr><tr><td>co_model_id</td><td><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>The id corresponding to the model used to compute CO</td></tr><tr><td>no_model_id</td><td><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>The id corresponding to the model used to compute NO</td></tr><tr><td>no2_model_id</td><td><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>The id corresponding to the model used to compute NO2</td></tr><tr><td>o3_model_id</td><td><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>The id corresponding to the model used to compute O3</td></tr><tr><td>co2_model_id</td><td><span data-option="sMTBc5UWaamS">final</span></td><td></td><td>The id corresponding to the model used to compute CO2</td></tr></tbody></table>

#### 3.1.3 Data Downloaded via the QuantAQ API

Data are available via the QuantAQ API at a 1-minute recording interval → the data available are the same as those available via the QuantAQ Cloud Console discussed above. The API is designed to allow engineers to build applications and map layers powered by the QuantAQ platform; however, it can also be a good way to automate data downloads, especially for large teams or lengthy download intervals. The data format is slightly different, as outlined below.

Each API call will return a paginated list of json objects with two keys: `data` and `meta`and will look something like the following:

```json
"meta": {
    "first_url": "https://api.quant-aq.com/device-api/v1/devices/MOD-00001/data/?page=1&per_page=50&limit=3",
    "last_url": "https://api.quant-aq.com/device-api/v1/devices/MOD-00001/data/?page=1&per_page=50&limit=3",
    "next_url": null,
    "page": 1,
    "pages": 1,
    "per_page": 50,
    "prev_url": null,
    "total": 3
  }
```

The key definitions can be described as:

`first_url`: The unique url for the first page of data in the query

`last_url`: The unique url for the last page of data in the query

`next_url`: The unique url for the next page of data in the query

`prev_url`: The unique url for the previous page of data in the query

`page`: The current page number

`pages`: The total number of pages available for the query

`per_page`: The number of data objects per page

`total`: The total number of data objects in the query

The `data` object contains a list of all individual data objects for that page of data. You can query either the **raw** or the **final** data, both of which have different data values available. The **final** endpoint will return the following and will be different depending on the product SKU:

```json
"data": [
    {
      "co": 132.63,
      "geo": {
        "lat": 19.451,
        "lon": -155.879
      },
      "met": {
        "rh": 69.6,
        "temp": 20,
        "wd": 15.1,
        "ws": 5.25
      },
      "model": {
        "gas": {},
        "pm": {
          "pm1": 4692,
          "pm10": 4694,
          "pm25": 4693
        }
      },
      "pm1": 0.53,
      "pm10": 24.59,
      "pm25": 3.64,
      "rh": 69.6,
      "sn": "MOD-00001",
      "so2": 6.35,
      "temp": 20,
      "timestamp": "2022-12-20T17:54:57",
      "timestamp_local": "2022-12-20T07:54:57",
      "url": "https://api.quant-aq.com/device-api/v1/devices/MOD-00001/data/23523900",
      "wd": 15.1,
      "ws": 5.25
    },
		{...},
		{...},
]
```

It contains several objects including the `geo`, `met`, and `model` objects. The descriptions of the individual data points are mapped to their respective columns in Section 3.1.2 above.

*Note: If nothing appears in the right-hand column, the variable definition/name is the same*

| `geo.lat`                             | `lat`                                                  |
| ------------------------------------- | ------------------------------------------------------ |
| `geo.lon`                             | `lon`                                                  |
| `met.wd`                              | `wd`                                                   |
| `met.ws`                              | `ws`                                                   |
| `met.rh`                              | `rh`                                                   |
| `met.temp`                            | `temp`                                                 |
| `model.pm.pm1`                        | `pm1_model_id`                                         |
| `model.pm.pm25`                       | `pm25_model_id`                                        |
| `model.pm.pm10`                       | `pm10_model_id`                                        |
| `pm1`                                 |                                                        |
| `pm25`                                |                                                        |
| `pm10`                                |                                                        |
| `co`, `no`, `no2`, `o3`, `so2`, `co2` | Pending SKU, you may have one or more of these columns |
| `sn`                                  |                                                        |
| `timestamp`                           |                                                        |
| `timestamp_local`                     |                                                        |
| `url`                                 | The unique url for this data point.                    |

### 3.2 Understanding the Status Flag

Each row of data contains a single-byte data flag that describes the current state of the device. Flags are stored as unsigned integers and contain encoded information about each of the sensors on board. They are generated via a bitmask and can be decoded by reversing the procedure. To determine whether a specific flag is set, you can use the bitwise AND operation. If the flag's value is returned, then it is set. If a zero is returned, it is not set. This can seem complicated, so let's clear it up with a simple example.

Let's assume the value of the flag column is set to 4. We can perform a bitwise AND operation to check the result to see if FLAG\_STARTUP was set (it wasn't). Below, we will check to see if the flag for the nephelometer is set (it is!).

```python
# bit AND - is FLAG_STARTUP set?
>>> 4 & 1
0

# bit AND - is FLAG_NEPH set?
>>> 4 & 4
4
```

The following table describes the flags, their value, and what they mean.

The following table describes the flags, their value, and what they mean.

<table><thead><tr><th width="192">FLAG</th><th width="88">VALUE</th><th>WHY IS IT SET?</th><th>WHAT TO DO?</th></tr></thead><tbody><tr><td>FLAG_STARTUP</td><td>1</td><td>This flag is set when the device powers on.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_OPC</td><td>2</td><td>This flag is set when the OPC has indicated the data failed to transfer correctly. This can be caused by the fan being off, the laser being off, or the checksum not validating properly.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_NEPH</td><td>4</td><td>This flag is set when the nephelometer has indicated the data failed to transfer correctly.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_RHTP</td><td>8</td><td>This flag is set when the relative humidity and temperature sensor has failed.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_CO</td><td>16</td><td>This flag is set when the CO sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_NO</td><td>32</td><td>This flag is set when the NO sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_NO2</td><td>64</td><td>This flag is set when the NO2 sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_O3</td><td>128</td><td>This flag is set when the O3 sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_CO2</td><td>256</td><td>This flag is set when the CO2 sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_SO2</td><td>512</td><td>This flag is set when the SO2 sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_H2S</td><td>1024</td><td>This flag is set when the H2S sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_BAT</td><td>2048</td><td>This flag is set when the internal LiPo battery is low or dead.</td><td>None.</td></tr><tr><td>FLAG_OVERHEAT</td><td>4096</td><td>This flag is set when the OPC has overheated.</td><td>Contact QuantAQ.</td></tr><tr><td>FLAG_SD</td><td>8192</td><td>This flag is set when the SD card has failed.</td><td>Replace the SD card.</td></tr></tbody></table>

### 3.3 Leveraging QuantAQ's Software Tools

To make data analysis easier, QuantAQ maintains several software programs designed to reduce the time you spend munging and cleaning your data. The most relevant piece of software is going to be the QuantAQ CLI (command line interface). The CLI can be used to easily concatenate files, merge files together, and de-code the flag and NaN bad data. It is quite simple to go from a large folder full of files to a clean, munged data file in less than a few commands. Full documentation and use cases can be found on the QuantAQ CLI website.

{% embed url="<https://github.com/quant-aq/cli>" %}

## 4. Maintenance and Service

There are no consumable or user-replaceable components to the MODULAIR-PM. If you believe a component is broken or not functioning correctly, please contact support via the in-app chat.

### 4.1 Reporting Issues

As a new product, issues will likely arise with the hardware, firmware, software, or all three! We do our best to prevent issues from arising and will be timely in fixing any that do arise. If you experience an issue or have a suggestion related to the MODULAIR hardware, please check the [knowledge base](https://support.quant-aq.com/). If you do not find the answer you're looking for in the [knowledge base](https://support.quant-aq.com/), you can open a ticket via the in-app chat.

## 5. Changelog

### 5.1 Hardware Changes

<table><thead><tr><th width="174">DATE</th><th>VERSION</th><th>CHANGES</th></tr></thead><tbody><tr><td>October 2021</td><td>0.1.0</td><td>First production release. No changes at this time.</td></tr></tbody></table>

### 5.2 Firmware Changes

Please see our [public changelog](https://changes.quant-aq.com/) for a full history of all firmware support changes.

## 6. Appendix

### 6.1 Wiring Diagrams

Coming soon!

### 6.2 LED Indicator Status and Meaning

The LED indicator on the front panel is used to communicate the status of the cellular and cloud communication status. The LED changes color and mode, each of which indicates a different state as outlined below. The rate at which the LED blinks comes in two flavors: blinking and breathing, where breathing implies a slow pulse where the color of the LED fades in and out.

<table><thead><tr><th width="123">LED COLOR</th><th width="140">PATTERN</th><th width="152">MODE</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>Green</td><td>Blinking</td><td>Looking for internet</td><td>If your device is blinking green, it is trying to connect to the cellular network. There is no need to take any action.</td></tr><tr><td></td><td>Breathing</td><td>Cloud not connected</td><td>If your device is breathing green, it has a cellular connection but has not been able to connect to the cloud.</td></tr><tr><td>Cyan</td><td>Blinking</td><td>Connecting to the cloud</td><td>Blinking cyan indicates the device has a cellular connection and is attempting to connect to the cloud. There is no need to take any action. This will happen each time on device startup.</td></tr><tr><td></td><td>Breathing</td><td>Connected</td><td>When your device is breathing cyan, everything is good and you are happily connected to the internet and the QuantAQ Cloud.</td></tr><tr><td>Magenta</td><td>Blinking</td><td>Firmware Update</td><td>When your device is blinking magenta, it is undergoing an over-the-air firmware update. DO NOT power off when this is happening.</td></tr><tr><td>White</td><td>Breathing</td><td>Cellular Off</td><td>If the LED is breathing white, the cellular connection has been turned off. If you did not explicitly turn off the cellular connection via the on-board switch, please notify QuantAQ.</td></tr><tr><td>Red</td><td>Blinking</td><td>System Failure</td><td>A system failure has occurred. This is likely caused by faulty on-board firmware or corrupted memory. Please contact QuantAQ for next steps.</td></tr></tbody></table>


# MODULAIR

Product manual for the 2025 generation of MODULAIR (i.e., MODULAIR-X).

| Key              | Value                                                                             |                               |
| ---------------- | --------------------------------------------------------------------------------- | ----------------------------- |
| **Product Name** | MODULAIR                                                                          |                               |
| **SKU(s)**       | MOD-X-015-NORAM                                                                   | For use in North America      |
|                  | MOD-X-015-GLOBAL                                                                  | For use outside North America |
| **Datasheet**    | [Download](https://assets.quant-aq.com/downloads/spec-sheets/modulair.latest.pdf) |                               |

## 1. Introduction and Specs

MODULAIR™ provides real-time estimates of particulate matter concentrations (PM1, PM2.5, and PM10), the particle size distribution, and four gas-phase pollutants (CO, NO, NO2, O3). MODULAIR™ uses the same patented particle measurement technology found in the MODULAIR-PM, which combines nephelometry with single-particle scattering to accurately measure aerosol loadings across a variety of environments.

MODULAIR™ is designed as an internet-connected device and does not work as intended without an internet connection. All MODULAIR™ devices are multi-radio and come equipped with an LTE modem and Wi-Fi, and can seamlessly transition between the two radios.

MODULAIR™ is designed to work with QuantAQ's add-on systems, including the [Smart Solar Power System](https://quant-aq.com/products/smart-solar-power-system) and [Gill Weather Stations](https://quant-aq.com/products/weather-station).

MODULAIR™ is protected by US Patent No. US 12,265,007 as well as multiple pending patents.

### 1.1 Specifications

#### 1.1.1 Air Quality Measurements

| PARAMETER                  | RANGE                          | ACCURACY                    |
| -------------------------- | ------------------------------ | --------------------------- |
| PM1, PM2.5, PM10           | 0 to 2,000 µg/m3               | Please refer to spec sheet. |
| Particle Size Distribution | 0.35 to 40.0 µm (24 size bins) | Not yet determined.         |
| Ozone (O3)                 | 0 to 250 ppb                   | 5 ppb or 20%                |
| Carbon Monoxide (CO)       | 0 to 13,000 ppb                | 70 ppb or 20%               |
| Nitrogen Oxide (NO)        | 0 to 2,500 ppb                 | 5 ppb or 35%                |
| Nitrogen Dioxide (NO2)     | 0 to 2,500 ppb                 | 5 ppb or 35%                |

For more information on the operating principle and performance of the MODULAIR, please refer to the following technical notes:

* QAN-003: [Evaluating the Performance of the MODULAIR-PM Particulate Matter Sensor in Jurupa Valley, CA](https://zenodo.org/records/11200301)
* QAN-004: [Evaluating the MODULAIR gas measurements against EPA Air Sensor Performance Targets](https://zenodo.org/records/14456513)

#### 1.1.2 Power and Communications

<table><thead><tr><th width="254.51171875">PARAMETER</th><th>DETAILS</th></tr></thead><tbody><tr><td>🔋 <strong>Power</strong></td><td>12V <br>1.25W average consumption</td></tr><tr><td>🗼 <strong>Communication</strong></td><td><strong>North America</strong><br>LTE Cat M1 with 2G fallback<br>Wi-Fi (2.4 GHz or 5 GHz)<br><br><strong>Global</strong><br>LTE Cat 1 with 2G/3G fallback<br>Wi-Fi (2.4 GHz or 5 GHz)</td></tr><tr><td>📈 <strong>Data</strong></td><td>Web interface (quant-aq.com)<br>Programmatic access (QuantAQ API)<br>Local storage (µSD Card)</td></tr></tbody></table>

#### 1.1.3 Operating Specifications

<table><thead><tr><th width="268.0703125">PARAMETER</th><th>DETAILS</th></tr></thead><tbody><tr><td>Weatherproof rating</td><td>IP67</td></tr><tr><td>Operating temperature</td><td>-20º to 45ºC</td></tr><tr><td>Operating humidity</td><td>5 to 95%, non-condensing</td></tr><tr><td>Dimensions</td><td>11.04" x 9.04" x 5.72"</td></tr><tr><td>Weight</td><td>6 lbs (2.72 kg)</td></tr></tbody></table>

### 1.2 Certifications

#### 1.2.1 FCC 15(b)

The MODULAIR™ air quality sensor complies with part 15 of the FCC rules for class A devices. Operation is subject to the following two conditions: (1) this device may not cause harmful interference; (2) this device must accept any interference received, including interference that may cause undesired operation. The MODULAIR™ contains a pre-certified multi-radio modem (2AEMI-M404).

<figure><img src="/files/qLLInXX2CCodcIi243ST" alt="" width="188"><figcaption></figcaption></figure>

## 2. Sensor Overview

### 2.1 Top View

Below is a top-down view of the MODULAIR. Air flows in through the port on the sensor base (Figure 2.2) and flows out the upper-right side of the sensor.&#x20;

<figure><img src="/files/Dal3dkGVCgShdxkPkwpe" alt=""><figcaption><p>Figure 2.1. A top-down view of the MODULAIR.</p></figcaption></figure>

### 2.2 Base View

The base of the MODULAIR highlights the air inlet port (center) and the three connection ports:

1. **M8 4P Solar Comms**. The upper-left port is for connecting the M8 RS-485 communication cable between the Smart Solar Power System (if purchased) and the MODULAIR. If not in use, ensure the M8 dust cap is in place to prevent damage to the instrument.
2. **M12 4P Power.** The lower-left port is for connecting the M12 power cable from either the Smart Solar Power System or the provided 12V power cable.
3. **M12 5P Weather Station.** The port on the right side is for connecting a supported Gill Weather Station. If not in use, ensure the M12 dust cap is in place to prevent damage to the instrument.

<figure><img src="/files/1Chv3T8ZRmR9ep5JsHyc" alt=""><figcaption><p>Figure 2.2. The MODULAIR base.</p></figcaption></figure>

Power can be provided directly to the M12, 4-pin cable. The pinout is documented below. If you are not using the QuantAQ Smart Solar Power System, you do not need to connect pins 2 and 3; leave them unpopulated.

<figure><img src="/files/TAHq1np3kkNdsEtNzJPR" alt=""><figcaption></figcaption></figure>

### 2.3 Internal View

#### 2.3.1 Front Panel

The front panel of the MODULAIR can be accessed by opening the lid of the enclosure. The panel provides access to the power switch, SD card, and Status LED, all of which are shown in Figure 2.3.

<figure><img src="/files/TLdLFaKdjlFAWUIKBB99" alt=""><figcaption><p>Figure 2.3. The internal front panel of the MODULAIR.</p></figcaption></figure>

#### 2.3.2 Core Board

{% hint style="info" %}
Under normal operating circumstances, it should not be necessary to access the Core Board directly. You should only do so under the advisement of the QuantAQ support team.
{% endhint %}

To access the Core Board, open the front panel after unscrewing the screw located just above the µSD card. Once open, you can access the **mode** and **reset** buttons and the **USB debugging port** for streaming logs. When closing the lid, make sure it is aligned such that you do not break off the µSD card slot.

<figure><img src="/files/q584oPENNLoQ7Bx3avlT" alt=""><figcaption><p>Figure 2.4. The Core Board that runs the MODULAIR.</p></figcaption></figure>

## 3. Installation and Hardware Setup

### 3.1 Unpacking

When unpacking your MODULAIR, you should expect to find the following:

1. MODULAIR Air Quality Sensor
2. 12V, 2A USB-C Power Brick
3. USB-C to M12 Power Cable
4. Device Registration Card
5. MODULAIR Pole Mount Kit

If any of these components are missing, please contact QuantAQ Support via the in-app chat.

### 3.2 Device Registration

{% hint style="info" %}
You do not need to physically have your MODULAIR present to complete the device registration process. The process can also be completed without powering up your device.
{% endhint %}

Each device ships with a **Registration Card** containing a QR code and a short confirmation code. Follow the instructions below to register your device:

{% stepper %}
{% step %}

### Scan the QR code

Using an internet-connected phone, tablet, or computer, scan the QR code on your Registration Card. It is best to first log in to quant-aq.com on the same device. The QR code should direct you to the registration page on the QuantAQ Cloud.
{% endstep %}

{% step %}

### Fill out the device registration form

Fill out the form presented on your screen.
{% endstep %}

{% step %}

### Enter the claim code

The form will ask you for a **Claim Code,** which can be found on your **Registration Card**. It is a 6-digit alphanumeric code. This ensures only the person in possession of the device can register it.

Once completed, press "Register".
{% endstep %}
{% endstepper %}

### 3.3 Configuring Wi-Fi

{% hint style="warning" %}
Please note that configuring Wi-Fi is \*not\* required for operation. All MODULAIR devices have cellular modems, and Wi-Fi is a fallback in the event you are operating in an area that does not have a reliable cellular connection.
{% endhint %}

{% hint style="info" %}
To use our web-based configuration tool, you must use a computer operating system and browser that supports WebUSB technology. Examples include Chrome, Edge, and Opera browsers on Windows, Mac, Linux, or Chromebook devices.
{% endhint %}

To configure Wi-Fi credentials for your device, use our [web-based configuration tool](https://app.quant-aq.com/wifi-setup) or visit <https://app.quant-aq.com/wifi-setup>. Complete instructions can be found in our [Help Center](https://support.quant-aq.com/en/articles/10947910-configuring-wifi-credentials-on-supported-sensors). The MODULAIR can store up to ten separate credentials before they begin to be overwritten.&#x20;

### 3.4 Installation

{% hint style="info" %}
If the recommended installation hardware does not work for your deployment, please contact QuantAQ Support via the in-app chat, and we will help find a solution.
{% endhint %}

The MODULAIR should be mounted using the provided Pole Mount Kit. The Pole Mount Kit is designed to be installed using either the provided back plates and carriage bolts for smaller posts or hose clamps for larger posts. If an existing pole or post is not available in the location where you will be installing your sensor, we recommend acquiring a tripod or similar.

| Method                                    | Receommended Pole Diameter |
| ----------------------------------------- | -------------------------- |
| Pole Mount Kit with Back Plates           | 1.25" - 2"                 |
| Pole Mount Kit with Hose Clamps or Straps | 2" - 6"                    |

To physically install your sensor, follow these instructions:

{% stepper %}
{% step %}

### Secure the Pole Mount Kit

Secure the Pole Mount Kit to the pole or post using the included carriage bolts and backing plates, or hose clamps if securing to a larger post.

<figure><img src="/files/VlU2Titnkm2i3k3oi0OK" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Pre-Install the 3/8" 10-32 screws to the MODULAIR

Using the four provided 3/8" 10-32 screws, partially screw install each one into the fasteneres in each corner of the back of the MODULAIR.
{% endstep %}

{% step %}

### Secure the MODULAIR

Slide the four screws through the slots on the Pole Mount Kit and then secure.

<figure><img src="/files/iym7srZ2SGSiDwS9kfeL" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Install the Power Cord and Power On

Plug in the M12 to USB-C power cable, open the front panel of the MODULAIR, and turn the device *on* by pushing the power switch into the *on* position.

At this point, the Status LED on your MODULAIR will begin to blink, and within a few minutes, should begin breathing cyan, which indicates everything is working.&#x20;
{% endstep %}
{% endstepper %}

### 3.5 Connectivity Considerations

As all QuantAQ products are internet-connected, it is important to consider connectivity when choosing an installation location. There are three primary things to consider:

1. **Antenna Connection.** If your device has an external antenna, ensure it is seated securely and placed at a 90º angle pointing toward the sky.
2. **Antenna Placement.** Do not place the device near metal objects or other sources of RF (i.e., antenna). Keep the antenna at least 18" away from metal objects as they can cause distortions and reflections.
3. **Location and Cellular Availability.** Install your sensor in a location with a known cellular signal on the carriers we support.

## 4. Software and Data

### 4.1 Data Structure and Outputs

There are three ways in which you can access data for the MODULAIR:

1. Raw, 5-second data is stored locally on the µSD card
2. Data can be downloaded as a CSV via the QuantAQ Cloud console
3. Data can be downloaded via the QuantAQ Cloud API

The data formats are slightly different, though largely consistent. Each approach is documented below.

#### 4.1.1 Data stored locally (µSD Card)

Data is collected and saved to an onboard µSD card every 5- 10 seconds (depending on product SKU). Each minute, these values are averaged and pushed to the QuantAQ Cloud, where they are available for you to view, interact with, and download. It is unlikely you will ever *need* the locally stored data, but it is available to you if you would like to use it.&#x20;

On the µSD card, you will find data files with file names like DATA\_{YYYYMMDD}@FW{VERSION}.csv where YYYYMMDD represents the UTC date and VERSION represents the firmware version of the device. In the event a firmware update happens, a new file for that date will be created.&#x20;

<figure><img src="/files/dlZUAHXegtXtaplm6DbL" alt=""><figcaption><p>Figure 4.1. Sample of a data file header. The first three rows include meta data with subsequent rows containing data.</p></figcaption></figure>

Data files are written each day and can be read or analyzed using any programming language or spreadsheet program (e.g., Microsoft Excel). Each file begins with three metadata rows describing the device model (row 1), device ID (row 2), and device serial number (row 3). Row 4 contains the data column headers, and rows 5 and higher contain data. Each row corresponds to a new record.

Table 4.1 below documents the columns available in the downloaded data and what they mean.

<table><thead><tr><th width="201.94140625">COLUMN</th><th width="85.9921875" align="center">UNIT</th><th>Description</th></tr></thead><tbody><tr><td>timestamp</td><td align="center"></td><td>The sample timestamp in ISO format</td></tr><tr><td>fw</td><td align="center"></td><td>The current firmware version</td></tr><tr><td>flag</td><td align="center"></td><td>The status flag corresponding to this record</td></tr><tr><td>soc</td><td align="center">%</td><td>The state of charge of the onboard LiPo battery</td></tr><tr><td>sample_temp</td><td align="center">ºC</td><td>The in-box temperature</td></tr><tr><td>sample_rh</td><td align="center">%</td><td>The in-box relative humidity</td></tr><tr><td>bin0</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin0 (0.35 - 0.46 µm)</td></tr><tr><td>bin1</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin1 (0.46 - 0.66 µm)</td></tr><tr><td>bin2</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin2 (0.66 - 1.0 µm)</td></tr><tr><td>bin3</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin3 (1.0 - 1.3 µm)</td></tr><tr><td>bin4</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin4 (1.3 - 1.7 µm)</td></tr><tr><td>bin5</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin5 (1.7 - 2.3 µm)</td></tr><tr><td>bin6</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin6 (2.3 - 3.0 µm)</td></tr><tr><td>bin7</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin7 (3.0 - 4.0 µm)</td></tr><tr><td>bin8</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin8 (4.0 - 5.2 µm)</td></tr><tr><td>bin9</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin9 (5.2 - 6.5 µm)</td></tr><tr><td>bin10</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin10 (6.5 - 8.0 µm)</td></tr><tr><td>bin11</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin11 (8.0 - 10.0 µm)</td></tr><tr><td>bin12</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin12 (10.0 - 12.0 µm)</td></tr><tr><td>bin13</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin13 (12.0 - 14.0 µm)</td></tr><tr><td>bin14</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin14 (14.0 - 16.0 µm)</td></tr><tr><td>bin15</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin15 (16.0 - 18.0 µm)</td></tr><tr><td>bin16</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin16 (18.0 - 20.0 µm)</td></tr><tr><td>bin17</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin17 (20.0 - 22.0 µm)</td></tr><tr><td>bin18</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin18 (22.0 - 25.0 µm)</td></tr><tr><td>bin19</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin19 (25.0 - 28.0 µm)</td></tr><tr><td>bin20</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin20 (28.0 - 31.0 µm)</td></tr><tr><td>bin21</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin21 (31.0 - 34.0 µm)</td></tr><tr><td>bin22</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin22 (34.0 - 37.0 µm)</td></tr><tr><td>bin23</td><td align="center">p/cm3</td><td>Number of particles per cubic cm in the OPC's bin23 (37.0 - 40.0 µm)</td></tr><tr><td>bin1MToF</td><td align="center">ml/s</td><td>Time of flight for particles in OPC bin1</td></tr><tr><td>bin3MToF</td><td align="center">ml/s</td><td>Time of flight for particles in OPC bin3</td></tr><tr><td>bin5MToF</td><td align="center">ml/s</td><td>Time of flight for particles in OPC bin5</td></tr><tr><td>bin7MToF</td><td align="center">ml/s</td><td>Time of flight for particles in OPC bin7</td></tr><tr><td>opc_sample_flow</td><td align="center">ml/s</td><td>OPC sample flow rate</td></tr><tr><td>opc_temp</td><td align="center">ºC</td><td>The internal temperature of the OPC</td></tr><tr><td>opc_rh</td><td align="center">%</td><td>The internal relative humidity of the OPC</td></tr><tr><td>opc_pm1</td><td align="center">µg/m3</td><td>The factory-computed PM1 value for the OPC</td></tr><tr><td>opc_pm25</td><td align="center">µg/m3</td><td>The factory-computed PM2.5 value for the OPC</td></tr><tr><td>opc_pm10</td><td align="center">µg/m3</td><td>The factory-computed PM10 value for the OPC</td></tr><tr><td>opc_laser_status</td><td align="center"></td><td>The laser power of the OPC</td></tr><tr><td>neph_bin0</td><td align="center">p</td><td>Number of particles in bin0 of the nephelometer</td></tr><tr><td>neph_bin1</td><td align="center">p</td><td>Number of particles in bin1 of the nephelometer</td></tr><tr><td>neph_bin2</td><td align="center">p</td><td>Number of particles in bin2 of the nephelometer</td></tr><tr><td>neph_bin3</td><td align="center">p</td><td>Number of particles in bin3 of the nephelometer</td></tr><tr><td>neph_bin4</td><td align="center">p</td><td>Number of particles in bin4 of the nephelometer</td></tr><tr><td>neph_bin5</td><td align="center">p</td><td>Number of particles in bin5 of the nephelometer</td></tr><tr><td>neph_pm1_std</td><td align="center">µg/m3</td><td>The factory computed value for PM1 from the Nephelometer</td></tr><tr><td>neph_pm25_std</td><td align="center">µg/m3</td><td>The factory computed value for PM2.5 from the Nephelometer</td></tr><tr><td>neph_pm10_std</td><td align="center">µg/m3</td><td>The factory computed value for PM10 from the Nephelometer</td></tr><tr><td>neph_pm1_env</td><td align="center">µg/m3</td><td>The factory computed value for PM1 from the Nephelometer</td></tr><tr><td>neph_pm25_env</td><td align="center">µg/m3</td><td>The factory computed value for PM2.5 from the Nephelometer</td></tr><tr><td>neph_pm10_env</td><td align="center">µg/m3</td><td>The factory computed value for PM10 from the Nephelometer</td></tr><tr><td>dd_operating_state</td><td align="center"></td><td>The operating state of the DualDetector</td></tr><tr><td>dd_measurement_state</td><td align="center"></td><td>The measurement state of the DualDetector</td></tr><tr><td>wx_ws</td><td align="center">m/s</td><td>Vector wind speed measured by the Gill weather station, if equipped</td></tr><tr><td>wx_wd</td><td align="center">deg</td><td>Wind direction measured by the Gill weather station, if equipped</td></tr><tr><td>wx_ws_scalar</td><td align="center">m/s</td><td>Scalar wind speed measured by the Gill weather station, if equipped</td></tr><tr><td>wx_u</td><td align="center"></td><td>u component of the wind speed and direction measured by the Gill weather station, if equipped</td></tr><tr><td>wx_v</td><td align="center"></td><td>v component of the wind speed and direction measured by the Gill weather station, if equipped</td></tr><tr><td>wx_pressure</td><td align="center">hPa</td><td>Ambient pressure measured by the Gill weather station, if equipped</td></tr><tr><td>wx_temp</td><td align="center">ºC</td><td>Ambient temperature measured by the Gill weather station, if equipped</td></tr><tr><td>wx_rh</td><td align="center">%</td><td>Ambient relative humidity measured by the Gill weather station, if equipped</td></tr><tr><td>wx_dew_point</td><td align="center">ºC</td><td>Dew point measured by the Gill weather station, if equipped</td></tr><tr><td>co_we</td><td align="center">mV</td><td>Working electrode signal for the CO sensor</td></tr><tr><td>co_ae</td><td align="center">mV</td><td>Auxiliary electrode signal for the CO sensor</td></tr><tr><td>no_we</td><td align="center">mV</td><td>Working electrode signal for the NO sensor</td></tr><tr><td>no_ae</td><td align="center">mV</td><td>Auxiliary electrode signal for the NO sensor</td></tr><tr><td>no2_we</td><td align="center">mV</td><td>Working electrode signal for the NO2 sensor</td></tr><tr><td>no2_ae</td><td align="center">mV</td><td>Auxiliary electrode signal for the NO2 sensor</td></tr><tr><td>o3_we</td><td align="center">mV</td><td>Working electrode signal for the O3 sensor</td></tr><tr><td>o3_ae</td><td align="center">mV</td><td>Auxiliary electrode signal for the O3 sensor</td></tr></tbody></table>

#### 4.1.2 Data stored remotely (QuantAQ Cloud)

Data are pushed to the QuantAQ Cloud with 1-minute time resolution and can be downloaded via the API or via the web app as a CSV. When downloading data, you can select whether you would like to download the *raw* data, *final* data, or *raw+final* data. Generally, the *final* data is what is desired, as it contains the final, cleaned data that is ready for analysis. The *raw* data is well-suited for researchers trying to investigate specific questions. When downloaded, the data is exported as a CSV and contains the following columns:

<table><thead><tr><th width="177.71484375">COLUMN</th><th width="160.375">FILE LOCATION<select multiple><option value="6I745FT8JxR0" label="raw" color="blue"></option><option value="4MiM2XQVepGk" label="final" color="blue"></option></select></th><th width="110.01171875">UNIT</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>timestamp</td><td><span data-option="6I745FT8JxR0">raw, </span><span data-option="4MiM2XQVepGk">final</span></td><td></td><td>The sample timestamp in ISO format</td></tr><tr><td>timestamp_local</td><td><span data-option="6I745FT8JxR0">raw, </span><span data-option="4MiM2XQVepGk">final</span></td><td></td><td>The local sample timestamp in ISO format</td></tr><tr><td>id</td><td><span data-option="6I745FT8JxR0">raw, </span><span data-option="4MiM2XQVepGk">final</span></td><td></td><td>The record ID</td></tr><tr><td>sn</td><td><span data-option="6I745FT8JxR0">raw, </span><span data-option="4MiM2XQVepGk">final</span></td><td></td><td>The device serial number</td></tr><tr><td>device_state</td><td><span data-option="6I745FT8JxR0">raw</span></td><td></td><td>The device state</td></tr><tr><td>lat</td><td><span data-option="6I745FT8JxR0">raw, </span><span data-option="4MiM2XQVepGk">final</span></td><td></td><td>The device location, latitude</td></tr><tr><td>lon</td><td><span data-option="6I745FT8JxR0">raw, </span><span data-option="4MiM2XQVepGk">final</span></td><td></td><td>The device location, longitude</td></tr><tr><td>sample_rh</td><td><span data-option="6I745FT8JxR0">raw, </span><span data-option="4MiM2XQVepGk">final</span></td><td>%</td><td>The in-box relative humidity</td></tr><tr><td>sample_temp</td><td><span data-option="6I745FT8JxR0">raw, </span><span data-option="4MiM2XQVepGk">final</span></td><td>ºC</td><td>The in-box temperature</td></tr><tr><td>wx_ws</td><td><span data-option="6I745FT8JxR0">raw, </span><span data-option="4MiM2XQVepGk">final</span></td><td>m/s</td><td>Vector wind speed measured by the Gill weather station, if equipped</td></tr><tr><td>wx_wd</td><td><span data-option="6I745FT8JxR0">raw, </span><span data-option="4MiM2XQVepGk">final</span></td><td>deg</td><td>Wind direction measured by the Gill weather station, if equipped</td></tr><tr><td>wx_ws_scalar</td><td><span data-option="6I745FT8JxR0">raw, </span><span data-option="4MiM2XQVepGk">final</span></td><td>m/s</td><td>Scalar wind speed measured by the Gill weather station, if equipped</td></tr><tr><td>wx_u</td><td><span data-option="6I745FT8JxR0">raw</span></td><td></td><td>u component of the wind speed and direction measured by the Gill weather station, if equipped</td></tr><tr><td>wx_v</td><td><span data-option="6I745FT8JxR0">raw</span></td><td></td><td>v component of the wind speed and direction measured by the Gill weather station, if equipped</td></tr><tr><td>wx_pressure</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>hPa</td><td>Ambient pressure measured by the Gill weather station, if equipped</td></tr><tr><td>wx_temp</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>ºC</td><td>Ambient temperature measured by the Gill weather station, if equipped</td></tr><tr><td>wx_rh</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>%</td><td>Ambient relative humidity measured by the Gill weather station, if equipped</td></tr><tr><td>wx_dew_point</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>ºC</td><td>Dew point measured by the Gill weather station, if equipped</td></tr><tr><td>bin0</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin0 (0.35 - 0.46 µm)</td></tr><tr><td>bin1</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin1 (0.46 - 0.66 µm)</td></tr><tr><td>bin2</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin2 (0.66 - 1.0 µm)</td></tr><tr><td>bin3</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin3 (1.0 - 1.3 µm)</td></tr><tr><td>bin4</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin4 (1.3 - 1.7 µm)</td></tr><tr><td>bin5</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin5 (1.7 - 2.3 µm)</td></tr><tr><td>bin6</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin6 (2.3 - 3.0 µm)</td></tr><tr><td>bin7</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin7 (3.0 - 4.0 µm)</td></tr><tr><td>bin8</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin8 (4.0 - 5.2 µm)</td></tr><tr><td>bin9</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin9 (5.2 - 6.5 µm)</td></tr><tr><td>bin10</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin10 (6.5 - 8.0 µm)</td></tr><tr><td>bin11</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin11 (8.0 - 10.0 µm)</td></tr><tr><td>bin12</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin12 (10.0 - 12.0 µm)</td></tr><tr><td>bin13</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin13 (12.0 - 14.0 µm)</td></tr><tr><td>bin14</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin14 (14.0 - 16.0 µm)</td></tr><tr><td>bin15</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin15 (16.0 - 18.0 µm)</td></tr><tr><td>bin16</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin16 (18.0 - 20.0 µm)</td></tr><tr><td>bin17</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin17 (20.0 - 22.0 µm)</td></tr><tr><td>bin18</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin18 (22.0 - 25.0 µm)</td></tr><tr><td>bin19</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin19 (25.0 - 28.0 µm)</td></tr><tr><td>bin20</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin20 (28.0 - 31.0 µm)</td></tr><tr><td>bin21</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin21 (31.0 - 34.0 µm)</td></tr><tr><td>bin22</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin22 (34.0 - 37.0 µm)</td></tr><tr><td>bin23</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p/cc</td><td>Number of particles per cubic cm in the OPC's bin23 (37.0 - 40.0 µm)</td></tr><tr><td>opc_pm1</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>µgm<sup>-3</sup></td><td>The factory-computed PM<sub>1</sub> value for the OPC</td></tr><tr><td>opc_pm25</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>µgm<sup>-3</sup></td><td>The factory-computed PM<sub>2.5</sub> value for the OPC</td></tr><tr><td>opc_pm10</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>µµgm<sup>-3</sup></td><td>The factory-computed PM<sub>10</sub> value for the OPC</td></tr><tr><td>pm1_env</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>µgm<sup>-3</sup></td><td>The factory computed value for PM<sub>1</sub> from the Nephelometer</td></tr><tr><td>pm25_env</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>µgm<sup>-3</sup></td><td>The factory computed value for PM<sub>2.5</sub> from the Nephelometer</td></tr><tr><td>pm10_env</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>µgm<sup>-3</sup></td><td>The factory computed value for PM<sub>10</sub> from the Nephelometer</td></tr><tr><td>neph_bin0</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>p</td><td>Number of particles in bin0 of the nephelometer</td></tr><tr><td>dd_operating_state</td><td><span data-option="6I745FT8JxR0">raw</span></td><td></td><td>The operating state of the DualDetector</td></tr><tr><td>co_we</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>mV</td><td>Working electrode signal for the CO sensor</td></tr><tr><td>co_ae</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>mV</td><td>Auxiliary electrode signal for the CO sensor</td></tr><tr><td>co_diff</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>mV</td><td>Difference between working and auxiliary electrodes for the CO sensor</td></tr><tr><td>no_we</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>mV</td><td>Working electrode signal for the NO sensor</td></tr><tr><td>no_ae</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>mV</td><td>Auxiliary electrode signal for the NO sensor</td></tr><tr><td>no_diff</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>mV</td><td>Difference between working and auxiliary electrodes for the NO sensor</td></tr><tr><td>no2_we</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>mV</td><td>Working electrode signal for the NO<sub>2</sub> sensor</td></tr><tr><td>no2_ae</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>mV</td><td>Auxiliary electrode signal for the NO<sub>2</sub> sensor</td></tr><tr><td>no2_diff</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>mV</td><td>Difference between working and auxiliary electrodes for the NO<sub>2</sub> sensor</td></tr><tr><td>o3_we</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>mV</td><td>Working electrode signal for the O<sub>3</sub> sensor</td></tr><tr><td>o3_ae</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>mV</td><td>Auxiliary electrode signal for the O<sub>3</sub> sensor</td></tr><tr><td>ox_diff</td><td><span data-option="6I745FT8JxR0">raw</span></td><td>mV</td><td>Difference between working and auxiliary electrodes for the O<sub>3</sub> sensor</td></tr><tr><td>pm1</td><td><span data-option="4MiM2XQVepGk">final</span></td><td>µgm<sup>-3</sup></td><td>Final PM<sub>1</sub> value</td></tr><tr><td>pm25</td><td><span data-option="4MiM2XQVepGk">final</span></td><td>µgm<sup>-3</sup></td><td>Final PM<sub>2.5</sub> value</td></tr><tr><td>pm10</td><td><span data-option="4MiM2XQVepGk">final</span></td><td>µgm<sup>-3</sup></td><td>Final PM<sub>10</sub> value</td></tr><tr><td>co</td><td><span data-option="4MiM2XQVepGk">final</span></td><td>ppb</td><td>Final CO value</td></tr><tr><td>no</td><td><span data-option="4MiM2XQVepGk">final</span></td><td>ppb</td><td>Final NO value</td></tr><tr><td>no2</td><td><span data-option="4MiM2XQVepGk">final</span></td><td>ppb</td><td>Final NO<sub>2</sub> value</td></tr><tr><td>o3</td><td><span data-option="4MiM2XQVepGk">final</span></td><td>ppb</td><td>Final O<sub>3</sub> value</td></tr></tbody></table>

### 4.2 Understanding the Status Flag

Each record contains a status flag, stored as an unsigned integer, that describes the state of the device for that exact record. Flags contain encoded information about each of the sub-components onboard the device. They are generated via a bitmask and can be decoded by reversing the procedure. To determine whether a specific flag is set, you can use the bitwise AND operator. If the value of the flag is returned, then the flag is set. If a zero is returned, the flag is *not* set.&#x20;

To make this a bit clearer, let's follow this example. Let's assume the value of the flag is set to "4". We can perform a bitwise AND operation to check the result to see if FLAG\_STARTUP is set.

```
# bit AND - is FLAG_STARTUP set?
>>> 4 & 1
0

# bit AND - is FLAG_NEPH set?
>>> 4 & 4
4
```

The table below describes the available flags, flag values, and a description of what they mean and what action should be taken when they are set.&#x20;

{% hint style="info" %}
Flags are consistent across all QuantAQ products, so there may be flags in the table below that irrelevant to your product.
{% endhint %}

<table><thead><tr><th width="169.62109375">FLAG</th><th width="90.24609375">VALUE</th><th width="221.5234375">WHY IS IT SET?</th><th>WHAT TO DO?</th></tr></thead><tbody><tr><td>FLAG_STARTUP</td><td>1</td><td>This flag is set when the device powers on.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_OPC</td><td>2</td><td>This flag is set when the OPC has indicated the data failed to transfer correctly. This can be caused by the fan being off, the laser being off, or the checksum not validating properly.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_NEPH</td><td>4</td><td>This flag is set when the nephelometer has indicated the data failed to transfer correctly.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_RHTP</td><td>8</td><td>This flag is set when the relative humidity and temperature sensor has failed.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_CO</td><td>16</td><td>This flag is set when the CO sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_NO</td><td>32</td><td>This flag is set when the NO sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_NO2</td><td>64</td><td>This flag is set when the NO2 sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_O3</td><td>128</td><td>This flag is set when the O3 sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_CO2</td><td>256</td><td>This flag is set when the CO2 sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_SO2</td><td>512</td><td>This flag is set when the SO2 sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_H2S</td><td>1024</td><td>This flag is set when the H2S sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_BAT</td><td>2048</td><td>This flag is set when the internal LiPo battery is low or dead.</td><td>None.</td></tr><tr><td>FLAG_OVERHEAT</td><td>4096</td><td>This flag is set when the OPC has overheated.</td><td>Contact QuantAQ.</td></tr><tr><td>FLAG_SD</td><td>8192</td><td>This flag is set when the SD card has failed.</td><td>Replace the SD card.</td></tr></tbody></table>

### 4.3 Leveraging QuantAQ's Software Tools

To make data analysis easier, QuantAQ maintains several software programs designed to reduce the time it takes for you to go from data to insight. Below, we highlight several tools and their purpose:

**QuantAQ CLI**

The QuantAQ CLI is a simple Python-based tool for cleaning, munging, and interacting with data from QuantAQ devices.

{% embed url="<https://github.com/quant-aq/cli>" %}

**py-smps**

`py-smps` is a Python library for manipulating and analyzing size-resolved particle data from OPCs, SMPS, or other particle sizing instruments.

{% embed url="<https://github.com/quant-aq/py-smps>" %}

**atmospy**

`atmopsy` is a Python library for analyzing and visualizing air quality data.

{% embed url="<https://github.com/dhhagan/atmospy>" %}

**py-quantaq**

`py-quantaq` is a simple API wrapper for the QuantAQ Cloud API. It is the recommended method for downloading or interacting with data or devices when using Python.

{% embed url="<https://github.com/quant-aq/py-quantaq>" %}

**r-quantaq**

`r-quantaq` is a simple API wrapper for the QuantAQ Cloud API. It is the recommended method for downloading or interacting with data or devices when using R.

{% embed url="<https://github.com/quant-aq/r-quantaq>" %}

## 5. Maintenance and Service

There are no consumable or user-replaceable components to the MODULAIR. If you believe a component is broken or not functioning correctly, please contact Customer Support via the in-app chat.

Additional maintenance and service recommendations are coming soon.

## 6. Changelog

Please see our [public changelog](https://changes.quant-aq.com/) for a full history of all firmware changes.

## 7. Appendix

### 7.1 Status LED

The Status LED on the front panel is used to communicate the status of the internet connection. The LED changes color and pattern, each of which indicates a different state as outlined below. The rate at which the LED blinks comes in two flavors: *blinking* and *breathing,* where breathing implies a slow pulse where the color of the LED fades in and out.

<table><thead><tr><th width="143.58984375">LED COLOR</th><th width="97.0703125">PATTERN</th><th width="167.98046875">MODE</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>Green</td><td>Blinking</td><td>Looking for Internet</td><td>If your device is blinking green, it is trying to connect to the cellular network. There is no need to take any action.</td></tr><tr><td></td><td>Breathing</td><td>Cloud not Connected</td><td>If your device is breathing green, it has a cellular connection but has not been able to connect to the cloud.</td></tr><tr><td>Cyan</td><td>Blinking</td><td>Connecting to the Cloud</td><td>Blinking cyan indicates the device has a cellular connection and is attempting to connect to the cloud. There is no need to take any action. This will happen each time on device startup.</td></tr><tr><td></td><td>Breathing</td><td>Connected</td><td>When your device is breathing cyan, everything is good and you are happily connected to the internet and the QuantAQ Cloud.</td></tr><tr><td>Magenta</td><td>Blinking</td><td>Firmware Update</td><td>When your device is blinking magenta, it is undergoing an over-the-air firmware update. DO NOT power off when this is happening.</td></tr><tr><td>White</td><td>Breathing</td><td>Internet Off</td><td>If the LED is breathing white, the cellular connection has been turned off. If you did not explicitly turn off the cellular connection via the onboard switch, please notify QuantAQ.</td></tr><tr><td>Red</td><td>Blinking</td><td>System Failure</td><td>A system failure has occurred. This is likely caused by faulty on-board firmware or corrupted memory. Please contact QuantAQ for next steps.</td></tr></tbody></table>


# MODULAIR-PM

Product manual for the MODULAIR-PM.

<table><thead><tr><th width="181">KEY</th><th width="199">VALUE</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><strong>Product Name</strong></td><td>MODULAIR-PM</td><td></td></tr><tr><td><strong>SKU(s)</strong></td><td>MOD-PM-NorAm</td><td>Pre-2025 version of the MODULAIR-PM for use in North America.</td></tr><tr><td></td><td>MOD-PM-Global</td><td>Pre-2025 version of the MODULAIR-PM for use outside of North America.</td></tr><tr><td><strong>Datasheet</strong></td><td><a href="https://assets.quant-aq.com/downloads/spec-sheets/modulair-pm.latest.pdf">Download</a></td><td></td></tr></tbody></table>

## 1. Introduction and Specs

MODULAIR™-PM provides real-time estimates of particulate matter concentrations (PM1, PM2.5, and PM10) and particle size distribution using a novel combination of multiple light-scattering-based particle sensors (patent pending).

### 1.1. Specifications

#### 1.1.1 Air Quality Measurements

| PARAMETER                  | RANGE                     | ACCURACY                   |
| -------------------------- | ------------------------- | -------------------------- |
| PM1, PM2.5, PM10           | 0 to 2,000 µg/m3          | Please see the spec sheet. |
| Particle size distribution | 0.35 to 40.0 µm (24 bins) | Not yet determined         |
| Temperature\*              | -40º to 85º C             | +/- 0.2ºC                  |
| Relative Humidity\*        | 0 to 100%                 | +/- 2%                     |

*\*Temperature and relative humidity are measured inside the flow cell and should not be interpreted as true ambient measurements.*

For more information on the operating principle and performance of the MODULAIR-PM, please refer to [QAN-001](https://zenodo.org/records/10688216) and [QAN-003](https://zenodo.org/records/11200301).

#### 1.1.2 Power and Communications

<table><thead><tr><th width="257">PARAMETER</th><th>DETAILS</th></tr></thead><tbody><tr><td>🔋 <strong>Power</strong></td><td>5V, 2A (supply)<br>250 mA average consumption</td></tr><tr><td>🗼 <strong>Communication</strong></td><td>LTE (North America)<br>3G/2G (Global)</td></tr><tr><td>📈 <strong>Data</strong></td><td>Web interface (quant-aq.com)<br>Programmatic access (QuantAQ API)<br>Local storage (µSD Card)</td></tr></tbody></table>

#### 1.1.3 Operating Specifications

| PARAMETER             | DETAILS                  |
| --------------------- | ------------------------ |
| Weatherproof rating   | IP68                     |
| Operating temperature | -20º to 45ºC             |
| Operating humidity    | 5 to 95%, non-condensing |
| Dimensions            | 6.59" x 6.59" x 5.11"    |
| Weight                | 4 lbs (1.8 kg)           |

### 1.2 Certifications

#### 1.2.1 FCC 15(b)

The MODULAIR™-PM air quality sensor complies with part 15 of the FCC rules for class A devices. Operation is subject to the following two conditions: (1) this device may not cause harmful interference; (2) this device must accept any interference received, including interference that may cause undesired operation.

<figure><img src="/files/A6w12CqSltBWoXsVOPGl" alt="" width="188"><figcaption></figcaption></figure>

Model: MODULAIR-PM

Contains FCC ID: 2AEMI-BRN402

#### 1.2.2 CE

The MODULAIR-PM complies with European Union EMC Directive 2014/30/EU and conforms to the following technical standards (EN 55011, EN 61326).

<figure><img src="/files/hlfLadE4Z8eX0Tlmpnqr" alt="" width="188"><figcaption></figcaption></figure>

## 2. Installation and Hardware Setup

### 2.1 Unpacking

When you unpack your device, you should have received the following:

* MODULAIR-PM Particulate Matter Sensor
* Power supply and USB-C power cable
* Mounting hardware (flanges with 4 10-32 screws)
* 16 GB µSD card

If any of these components are missing, please contact QuantAQ via support.quant-aq.com. If the shipping box contains multiple devices, you will receive the correct multiple of each component from the list above.

### 2.2 Instrument Layout

#### 2.2.1 Front Panel

The front panel of the device can be accessed by opening the lid of the enclosure. The panel provides access to the ON/OFF switch, Menu button, and LED indicator. Each component is labeled in Figure 2.1.

<figure><img src="/files/fLTzLDxSIOM7wrINIDWx" alt=""><figcaption><p>Figure 2.1: The MODULAIR-PM front panel consists of the ON/OFF switch, Status LED, and the µSD card slot.</p></figcaption></figure>

#### 2.2.2 Core Circuit Board

Underneath the front panel (which can be opened by removing the four No. 6 screws in the four corners), you will find the Core Circuit Board and µSD circuit board. While it is unlikely you will ever need to touch this, it is worth pointing out a few key components.

<figure><img src="/files/Tc46Wfinvnrgjq61Sun4" alt=""><figcaption><p>Figure 2.2. The Core Circuit Board includes connectors for the two particle sensors, a relative humidity and temperature sensor, and µSD circuit board. </p></figcaption></figure>

### 2.3 Connections and Device Registration

The MODULAIR-PM is shipped completely assembled, aside from the mounting hardware. Once the device is mounted and you have verified the power switch is in the OFF position, simply plug in the power supply and connect the USB-C cable in to the bottom of the device. Once the power cable is connected, simply flip the power switch to the ON position. Upon receiving power, the LED indicator (Figure 1) will flash green and eventually begin a sequence of slowly breathing cyan; this indicates the cellular connection is active and a session with the cloud server has begun. If the device is being powered on in a new location or has been powered off for an extended period of time, this may take some time to complete. The device will log data locally during this period and push the data to the server once a connection is established. If the LED indicator does not eventually begin breathing cyan, this indicates a cloud connectivity problem. Common errors and next steps can be found in Section 6.2.

To register your device, scan the QR code that is on the registration card you received with your device. It is easiest to complete this step using a cellphone or tablet with a working internet connection. A laptop with a functioning camera will also work, though may be more difficult. It is also suggested that you first log in to the website on the device you will use to complete this process. To register your device:

1. Use your camera to scan the QR code. This will open a tab in your default browser and will direct you to the device registration page.
2. Enter the fields for the information that the form asks for and click "Continue"
3. Enter the claim code found on the same QR code card - it should be a 6-character alphanumeric code.
4. Follow the instructions on the form and enter in data for the device location and other metadata. All of these can be changed in the future through the dashboard, so don't worry if you can't answer all questions at this time.

### 2.4 Installation

The device can be mounted in a number of ways depending on the exact use and available mounting options available to you. The device is shipped with mounting flanges which can be used to easily mount the device to a number of surfaces. Each flange is secured to the back of the device with two 10-32 x 0.75" stainless steel screws (included). Each flange includes three slots with the dimensions found below.

<figure><img src="/files/Z8wrM1mIhrKmy1CxGdFL" alt=""><figcaption><p>Figure 2.3: The dimensions for the mounting holes for the provided mounting flanges.</p></figcaption></figure>

Common installation approaches include:

* using high-strength zip ties to secure the device to a fence or post
* using screws to mount the device using the provided flanges

The complete box dimensions are:

* 7.04" x 7.04" x 5.72" (178.82 mm x 178.82 mm x 145.29 mm)

If a more secure approach is needed, a pole mount kit can be purchased directly from the supplier of the enclosures ([Polycase part number PL-087](https://www.polycase.com/pk-087)).

### 2.5 Connectivity Considerations

As all QuantAQ products are internet-connected, it is important to consider connectivity when choosing an installation location. There are three primary things to consider:

1. **Antenna Connection.** If your device has an external antenna, ensure it is seated securely and placed at a 90º angle pointing toward the sky.
2. **Antenna Placement.** Do not place the device near metal objects or other sources of RF (i.e., antenna). Keep the antenna at least 18" away from metal objects as they can cause distortions and reflections.
3. **Location and Cellular Availability.** Install your sensor in a location with a known cellular signal on the carriers we support.

## 3. Software Setup and Data

### 3.1 Data Structure and Outputs

There are three primary ways in which data can be accessed for the MODULAIR-PM:

1. Raw data is stored locally on the µSD card
2. Data can be downloaded from the QuantAQ Cloud Console
3. Data can be downloaded from the QuantAQ API

The data formats are slightly different depending on which method you’ve used to access the data, each of which is documented below.

#### 3.1.1 Data Stored Locally on the µSD Card

Data is collected and saved to the onboard µSD card every five seconds; every minute, these values are averaged and pushed to the cloud where they are available on the QuantAQ Cloud. It is unlikely you will ever need to use the locally saved data; however, it is there in case you need it. This section covers the locally stored data and how to understand it. When removing the µSD card to pull the data, make sure your device is turned OFF.

On the µSD card, you will find data files (with a prefix of DATA\_YYYYMMDD.csv) and log files which are located in the logs directory. Log files contain debugging information about the onboard sensors and the cellular communications module. It is unlikely these logs will be useful to most users, though they are available to you if you would like to view them. It is highly recommended that you use the QuantAQ CLI (discussed below) to analyze them, as it will vastly reduce the amount of time needed.

Data files are written each day and can be read or analyzed using any programming language or spreadsheet program (e.g., Microsoft Excel). Each file begins with three meta-data rows describing the device model (row 1), device ID (row 2), and device serial number (row 3). If you are automating your data analysis, you can skip these three rows. The fourth row contains the header information with the names for all columns. The remaining rows contain the data, where each row corresponds to a new 5-second sampling interval. The table below summarizes the columns.

| timestamp\_iso     |       | The sample timestamp in ISO format                         |
| ------------------ | ----- | ---------------------------------------------------------- |
| sample\_rh         | %     | Sample relative humidity                                   |
| sample\_temp       | ºC    | Sample temperature                                         |
|                    |       |                                                            |
| bin0               | p/cm3 | Number of particles per cubic cm in bin0 (0.35 - 0.46 µm)  |
| bin1               | p/cm3 | Number of particles per cubic cm in bin1 (0.46 - 0.66 µm)  |
| bin2               | p/cm3 | Number of particles per cubic cm in bin2 (0.66 - 1.0 µm)   |
| bin3               | p/cm3 | Number of particles per cubic cm in bin3 (1.0 - 1.3 µm)    |
| bin4               | p/cm3 | Number of particles per cubic cm in bin4 (1.3 - 1.7 µm)    |
| bin5               | p/cm3 | Number of particles per cubic cm in bin5 (1.7 - 2.3 µm)    |
| bin6               | p/cm3 | Number of particles per cubic cm in bin6 (2.3 - 3.0 µm)    |
| bin7               | p/cm3 | Number of particles per cubic cm in bin7 (3.0 - 4.0 µm)    |
| bin8               | p/cm3 | Number of particles per cubic cm in bin8 (4.0 - 5.2 µm)    |
| bin9               | p/cm3 | Number of particles per cubic cm in bin9 (5.2 - 6.5 µm)    |
| bin10              | p/cm3 | Number of particles per cubic cm in bin10 (6.5 - 8.0 µm)   |
| bin11              | p/cm3 | Number of particles per cubic cm in bin11 (8.0 - 10.0 µm)  |
| bin12              | p/cm3 | Number of particles per cubic cm in bin12 (10.0 - 12.0 µm) |
| bin13              | p/cm3 | Number of particles per cubic cm in bin13 (12.0 - 14.0 µm) |
| bin14              | p/cm3 | Number of particles per cubic cm in bin14 (14.0 - 16.0 µm) |
| bin15              | p/cm3 | Number of particles per cubic cm in bin15 (16.0 - 18.0 µm) |
| bin16              | p/cm3 | Number of particles per cubic cm in bin16 (18.0 - 20.0 µm) |
| bin17              | p/cm3 | Number of particles per cubic cm in bin17 (20.0 - 22.0 µm) |
| bin18              | p/cm3 | Number of particles per cubic cm in bin18 (22.0 - 25.0 µm) |
| bin19              | p/cm3 | Number of particles per cubic cm in bin19 (25.0 - 28.0 µm) |
| bin20              | p/cm3 | Number of particles per cubic cm in bin20 (28.0 - 31.0 µm) |
| bin21              | p/cm3 | Number of particles per cubic cm in bin21 (31.0 - 34.0 µm) |
| bin22              | p/cm3 | Number of particles per cubic cm in bin22 (34.0 - 37.0 µm) |
| bin23              | p/cm3 | Number of particles per cubic cm in bin23 (37.0 - 40.0 µm) |
| bin1MToF           | ml/s  | Time of flight for particles in bin1                       |
| bin3MToF           | ml/s  | Time of flight for particles in bin3                       |
| bin5MToF           | ml/s  | Time of flight for particles in bin5                       |
| bin7MToF           | ml/s  | Time of flight for particles in bin7                       |
| sample\_period     | s     | The sample period                                          |
| sample\_flow       | ml/s  | The sample flow rate                                       |
| opc\_temp          | ºC    | The internal temperature of the OPC                        |
| opc\_rh            | %     | The internal relative humidity of the OPC                  |
| opc\_pm1           | µg/m3 | The factory computed value for PM1 from the OPC            |
| opc\_pm25          | µg/m3 | The factory computed value for PM2.5 from the OPC          |
| opc\_pm10          | µg/m3 | The factory computed value for PM10 from the OPC           |
| laser\_status      |       | The status of the laser                                    |
| pm1\_std           | µg/m3 | The factory computed value for PM1 from the nephelometer   |
| pm25\_std          | µg/m3 | The factory computed value for PM2.5 from the nephelometer |
| pm10\_std          | µg/m3 | The factory computed value for PM10 from the nephelometer  |
| pm1\_env           | µg/m3 | The factory computed value for PM1 from the nephelometer   |
| pm25\_env          | µg/m3 | The factory computed value for PM2.5 from the nephelometer |
| pm10\_env          | µg/m3 | The factory computed value for PM10 from the nephelometer  |
| neph\_bin0         | p     | Number of particles in bin0 for the nephelometer           |
| neph\_bin1         | p     | Number of particles in bin1 for the nephelometer           |
| neph\_bin2         | p     | Number of particles in bin2 for the nephelometer           |
| neph\_bin3         | p     | Number of particles in bin3 for the nephelometer           |
| neph\_bin4         | p     | Number of particles in bin4 for the nephelometer           |
| neph\_bin5         | p     | Number of particles in bin5 for the nephelometer           |
| flag               |       | The status flag corresponding to this sample               |
| fw                 |       | The current firmware version                               |
| connection\_status |       | A boolean describing the state of the cellular connection  |

#### 3.1.2 Data Downloaded from the QuantAQ Cloud Console

Data are pushed to the QuantAQ Cloud with 1-minute time resolution and can be downloaded via the QuantAQ Cloud Console. When downloading data, you can select whether you would like to download the *raw* data, the *final* data, or both the *raw+final* data. Generally, the *final* data is what is desired, as it contains the final, cleaned data that is ready for analysis. The *raw* data is well-suited for researchers trying to investigate specific questions. When downloaded, the data is exported as a csv and contains the following columns:

<table data-header-hidden><thead><tr><th>COLUMN</th><th>FILE LOCATION<select multiple><option value="YXhyLtn6eHh5" label="raw" color="blue"></option><option value="HUUyQJ1omJov" label="final" color="blue"></option></select></th><th>UNITS</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>timestamp</td><td><span data-option="YXhyLtn6eHh5">raw, </span><span data-option="HUUyQJ1omJov">final</span></td><td></td><td>The sample timestamp in ISO format</td></tr><tr><td>timestamp_local</td><td><span data-option="YXhyLtn6eHh5">raw, </span><span data-option="HUUyQJ1omJov">final</span></td><td></td><td>The sample timestamp in ISO format, corrected for the timezone as defined in the device settings</td></tr><tr><td>id</td><td><span data-option="YXhyLtn6eHh5">raw, </span><span data-option="HUUyQJ1omJov">final</span></td><td></td><td>A unique id the corresponds to the record shown</td></tr><tr><td>sn</td><td><span data-option="YXhyLtn6eHh5">raw, </span><span data-option="HUUyQJ1omJov">final</span></td><td></td><td>The device serial number</td></tr><tr><td>sample_rh</td><td><span data-option="YXhyLtn6eHh5">raw, </span><span data-option="HUUyQJ1omJov">final</span></td><td>%</td><td>The sample relative humidity</td></tr><tr><td>sample_temp</td><td><span data-option="YXhyLtn6eHh5">raw, </span><span data-option="HUUyQJ1omJov">final</span></td><td>°C</td><td>The sample temperature</td></tr><tr><td>sample_pres</td><td><span data-option="HUUyQJ1omJov">final, </span><span data-option="YXhyLtn6eHh5">raw</span></td><td>mmHg</td><td>The sample pressure (available only on select devices)</td></tr><tr><td>bin0</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin0 (0.35 - 0.46 µm)</td></tr><tr><td>bin1</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin1 (0.46 - 0.66 µm)</td></tr><tr><td>bin2</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin2 (0.66 - 1.0 µm)</td></tr><tr><td>bin3</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin3 (1.0 - 1.3 µm)</td></tr><tr><td>bin4</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin4 (1.3 - 1.7 µm)</td></tr><tr><td>bin5</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin5 (1.7 - 2.3 µm)</td></tr><tr><td>bin6</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin6 (2.3 - 3.0 µm)</td></tr><tr><td>bin7</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin7 (3.0 - 4.0 µm)</td></tr><tr><td>bin8</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin8 (4.0 - 5.2 µm)</td></tr><tr><td>bin9</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin9 (5.2 - 6.5 µm)</td></tr><tr><td>bin10</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin10 (6.5 - 8.0 µm)</td></tr><tr><td>bin11</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin11 (8.0 - 10.0 µm)</td></tr><tr><td>bin12</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin12 (10.0 - 12.0 µm)</td></tr><tr><td>bin13</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin13 (12.0 - 14.0 µm)</td></tr><tr><td>bin14</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin14 (14.0 - 16.0 µm)</td></tr><tr><td>bin15</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin15 (16.0 - 18.0 µm)</td></tr><tr><td>bin16</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin16 (18.0 - 20.0 µm)</td></tr><tr><td>bin17</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin17 (20.0 - 22.0 µm)</td></tr><tr><td>bin18</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin18 (22.0 - 25.0 µm)</td></tr><tr><td>bin19</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin19 (25.0 - 28.0 µm)</td></tr><tr><td>bin20</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin20 (28.0 - 31.0 µm)</td></tr><tr><td>bin21</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin21 (31.0 - 34.0 µm)</td></tr><tr><td>bin22</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin22 (34.0 - 37.0 µm)</td></tr><tr><td>bin23</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>p/cm3</td><td>Number of particles per cubic cm in bin23 (37.0 - 40.0 µm)</td></tr><tr><td>opcn3_temp</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>C</td><td>The temperature of the onboard circuit board</td></tr><tr><td>opcn3_rh</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>%</td><td>The RH of the onboard circuit board</td></tr><tr><td>opcn3_pm1</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>µg/m3</td><td>Factory computed value of PM1 from the OPC</td></tr><tr><td>opcn3_pm25</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>µg/m3</td><td>Factory computed value of PM2.5 from the OPC</td></tr><tr><td>opcn3_pm10</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>µg/m3</td><td>Factory computed value of PM10 from the OPC</td></tr><tr><td>pm1_env</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>µg/m3</td><td>Factory computed value of PM1 from the nephelometer</td></tr><tr><td>pm25_env</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>µg/m3</td><td>Factory computed value of PM2.5 from the nephelometer</td></tr><tr><td>pm10_env</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>µg/m3</td><td>Factory computed value of PM10 from the nephelometer</td></tr><tr><td>neph_bin0</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>counts</td><td>The number of particles in bin0 from the nephelometer</td></tr><tr><td>neph_bin1</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>counts</td><td>The number of particles in bin1 from the nephelometer</td></tr><tr><td>neph_bin2</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>counts</td><td>The number of particles in bin2 from the nephelometer</td></tr><tr><td>neph_bin3</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>counts</td><td>The number of particles in bin3 from the nephelometer</td></tr><tr><td>neph_bin4</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>counts</td><td>The number of particles in bin4 from the nephelometer</td></tr><tr><td>neph_bin5</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td>counts</td><td>The number of particles in bin5 from the nephelometer</td></tr><tr><td>flag</td><td><span data-option="YXhyLtn6eHh5">raw</span></td><td></td><td>The status flag corresponding to this record</td></tr><tr><td>lat</td><td><span data-option="YXhyLtn6eHh5">raw, </span><span data-option="HUUyQJ1omJov">final</span></td><td>deg</td><td>The latitude of the device</td></tr><tr><td>lon</td><td><span data-option="YXhyLtn6eHh5">raw, </span><span data-option="HUUyQJ1omJov">final</span></td><td>deg</td><td>The longitude of the device</td></tr><tr><td>device_state</td><td><span data-option="YXhyLtn6eHh5">raw, </span><span data-option="HUUyQJ1omJov">final</span></td><td></td><td>The current state of the device</td></tr><tr><td>pm1</td><td><span data-option="HUUyQJ1omJov">final</span></td><td>µg/m3</td><td>The PM1 value</td></tr><tr><td>pm25</td><td><span data-option="HUUyQJ1omJov">final</span></td><td>µg/m3</td><td>The PM2.5 value</td></tr><tr><td>pm10</td><td><span data-option="HUUyQJ1omJov">final</span></td><td>µg/m3</td><td>The PM10 value</td></tr><tr><td>pm1_model_id</td><td><span data-option="HUUyQJ1omJov">final</span></td><td></td><td>The id corresponding to the model used to compute PM1</td></tr><tr><td>pm25_model_id</td><td><span data-option="HUUyQJ1omJov">final</span></td><td></td><td>The id corresponding to the model used to compute PM2.5</td></tr><tr><td>pm10_model_id</td><td><span data-option="HUUyQJ1omJov">final</span></td><td></td><td>The id corresponding to the model used to compute PM10</td></tr></tbody></table>

#### 3.1.3 Data Downloaded from the QuantAQ API

Data are available via the QuantAQ API at a 1-minute recording interval → the data available are the exact same as those available via the QuantAQ Cloud Console discussed above. The API is designed to allow engineers to build applications and map layers powered by the QuantAQ platform; however, it can also be a good way to automate data downloads, especially for large teams or lengthy download intervals. The data format is slightly different, as outlined below.

Each API call will return a paginated list of json objects with two keys: `data` and `meta`and will look something like the following:

```json
"meta": {
    "first_url": "https://api.quant-aq.com/device-api/v1/devices/MOD-PM-00001/data/?page=1&per_page=50&limit=3",
    "last_url": "https://api.quant-aq.com/device-api/v1/devices/MOD-PM-00001/data/?page=1&per_page=50&limit=3",
    "next_url": null,
    "page": 1,
    "pages": 1,
    "per_page": 50,
    "prev_url": null,
    "total": 3
  }
```

The key definitions can be described as:

`first_url`: The unique url for the first page of data in the query

`last_url`: The unique url for the last page of data in the query

`next_url`: The unique url for the next page of data in the query

`prev_url`: The unique url for the previous page of data in the query

`page`: The current page number

`pages`: The total number of pages available for the query

`per_page`: The number of data objects per page

`total`: The total number of data objects in the query

The `data` object contains a list of all individual data objects for that page of data. You can query either the **raw** or the **final** data, both of which have different data values available. The **final** endpoint will return the following:

```json
"data": [
    {
      "geo": {
        "lat": 33.7769,
        "lon": -84.4018
      },
      "met": {
        "pressure": 990.2,
        "rh": 10.54,
        "temp": 22.1
      },
      "model": {
        "pm": {
          "pm1": 8802,
          "pm10": 8804,
          "pm25": 8803
        }
      },
      "pm1": 1.293,
      "pm10": 1.297,
      "pm25": 1.297,
      "sn": "MOD-PM-00001",
      "timestamp": "2022-12-26T15:43:58",
      "timestamp_local": "2022-12-26T10:43:58",
      "url": "https://api.quant-aq.com/device-api/v1/devices/MOD-PM-00001/data/235414585"
    },
    {...},
    {...},
  ]
```

It contains several objects including the `geo`, `met`, and `model` objects. The descriptions of the individual data points are mapped to their respective columns in Section 3.1.2 above.

*Note: If nothing appears in the right-hand column, the variable definition/name is the same*

| `geo.lat`         | `lat`                               |
| ----------------- | ----------------------------------- |
| `geo.lon`         | `lon`                               |
| `met.pressure`    | `pressure`                          |
| `met.rh`          | `sample_rh`                         |
| `met.temp`        | `sample_temp`                       |
| `model.pm.pm1`    | `pm1_model_id`                      |
| `model.pm.pm25`   | `pm25_model_id`                     |
| `model.pm.pm10`   | `pm10_model_id`                     |
| `pm1`             |                                     |
| `pm25`            |                                     |
| `pm10`            |                                     |
| `sn`              |                                     |
| `timestamp`       |                                     |
| `timestamp_local` |                                     |
| `url`             | The unique url for this data point. |

For **raw** data, the template is similar, but the columns are slightly different as described below.

```json
"data": [
    {
      "flag": 0,
      "geo": {
        "lat": 33.7769,
        "lon": -84.4018
      },
      "met": {
        "pressure": 989.9,
        "rh": 10.32,
        "temp": 22.16
      },
      "neph": {
        "bin0": 210.25,
        "bin1": 63.083,
        "bin2": 3.75,
        "bin3": 0.417,
        "bin4": 0,
        "bin5": 0,
        "pm1": 0.333,
        "pm10": 0.5,
        "pm25": 0.5
      },
      "opc": {
        "bin0": 1.1973,
        "bin1": 0.0933,
        "bin10": 0,
        "bin11": 0,
        "bin12": 0,
        "bin13": 0,
        "bin14": 0,
        "bin15": 0,
        "bin16": 0,
        "bin17": 0,
        "bin18": 0,
        "bin19": 0,
        "bin2": 0.0242,
        "bin20": 0,
        "bin21": 0,
        "bin22": 0,
        "bin23": 0,
        "bin3": 0.007,
        "bin4": 0,
        "bin5": 0,
        "bin6": 0,
        "bin7": 0,
        "bin8": 0,
        "bin9": 0,
        "pm1": 0.18,
        "pm10": 0.21,
        "pm25": 0.21,
        "rh": 5.6,
        "temp": 28.9
      },
      "sn": "MOD-PM-00001",
      "timestamp": "2022-12-26T17:15:58",
      "timestamp_local": "2022-12-26T12:15:58",
      "url": "https://api.quant-aq.com/device-api/v1/devices/MOD-PM-00001/data/raw/235448331"
    },
		{...},
    {...},
  ],
```

| `flag`                          |                                     |
| ------------------------------- | ----------------------------------- |
| `geo.lat`                       | `lat`                               |
| `geo.lon`                       | `lon`                               |
| `met.pressure`                  | `pressure`                          |
| `met.rh`                        | `sample_rh`                         |
| `met.temp`                      | `sample_temp`                       |
| `neph.bin0` through `neph.bin5` | `neph_bin0` through `neph_bin5`     |
| `neph.pm1`                      | `pm1_env`                           |
| `neph.pm25`                     | `pm25_env`                          |
| `neph.pm10`                     | `pm10_env`                          |
| `opc.bin0` through `opc.bin23`  | `bin0` through `bin23`              |
| `opc.pm1`                       | `opcn3_pm1`                         |
| `opc.pm25`                      | `opcn3_pm25`                        |
| `opc.pm10`                      | `opcn3_pm10`                        |
| `opc.temp`                      | `opcn3_temp`                        |
| `opc.rh`                        | `opcn3_rh`                          |
| `sn`                            |                                     |
| `timestamp`                     |                                     |
| `timestamp_local`               |                                     |
| `url`                           | The unique url for this data point. |

### 3.2 Understanding and Decoding the Status Flag

Each row of data contains a single-byte data flag that describes the current state of the device. Flags are stored as unsigned integers and contain encoded information about each of the sensors onboard. They are generated via a bitmask and can be decoded by reversing the procedure. To determine whether a specific flag is set, you can use the bitwise AND operation. If the flag's value is returned, then it is set. If a zero is returned, it is not set. This can seem complicated, so let's clear it up with a simple example.

Let's assume the value of the flag column is set to 4. We can perform a bitwise AND operation to check the result to see if FLAG\_STARTUP was set (it wasn't). Below, we will check to see if the flag for the nephelometer is set (it is!).

```python
# bit AND - is FLAG_STARTUP set?
>>> 4 & 1
0

# bit AND - is FLAG_NEPH set?
>>> 4 & 4
4
```

The following table describes the flags, their value, and what they mean.

| FLAG\_STARTUP  | 1    | This flag is set when the device powers on.                                                                                                                                               | Remove any rows where this flag is set. |
| -------------- | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
| FLAG\_OPC      | 2    | This flag is set when the OPC has indicated the data failed to transfer correctly. This can be caused by the fan being off, the laser being off, or the checksum not validating properly. | Remove any rows where this flag is set. |
| FLAG\_NEPH     | 4    | This flag is set when the nephelometer has indicated the data failed to transfer correctly.                                                                                               | Remove any rows where this flag is set. |
| FLAG\_RHTP     | 8    | This flag is set when the relative humidity and temperature sensor has failed.                                                                                                            | Remove any rows where this flag is set. |
| FLAG\_OVERHEAT | 4096 | This flag is set when the OPC has overheated.                                                                                                                                             | Contact QuantAQ.                        |
| FLAG\_SD       | 8192 | This flag is set when the SD card has failed.                                                                                                                                             | Replace the SD card                     |

### 3.3 Leveraging QuantAQ's Software Tools

To make data analysis easier, QuantAQ maintains several software programs designed to reduce the time you spend munging and cleaning your data. The most relevant piece of software is going to be the QuantAQ CLI (command line interface). The CLI can be used to easily concatenate files, merge files together, and de-code the flag and NaN bad data. It is quite simple to go from a large folder full of files to a clean, munged data file in less than a few commands. Full documentation and use cases can be found on the QuantAQ CLI website.

{% embed url="<https://github.com/quant-aq/cli>" %}

### 3.4 Quality Assurance Protocols

This section details quality assurance (QA) protocols and tests performed at the sub-1-minute level on the device. Tests are performed at the sub-component level and are based on extensive research and knowledge of how our sensors perform across various environments. They are subject to change at any time and are released and documented with new firmware releases (see changes.quant-aq.com for more details and historical records). Details are provided below where possible, though some details are left vague to protect IP. Please contact QuantAQ via support if you have any remaining questions. QA procedures are broken down by sub-component below.

If a sub-component fails a QA test at the 5s level, it will be flagged and logged on the µSD card. If the QA test fails a the 1-minute level, the 1-minute data record will be flagged appropriately.

#### 3.4.1 Relative Humidity and Temperature

Each measurement is checked to ensure the relative humidity and temperature are within a realistic range for ambient measurements and within the specifications provided by the sensor manufacturer. In other words, the temperature at time t ($$T\_t$$) and relative humidity at time t ($$RH\_t$$) are checked to ensure they are within a specified range.

$$
T\_{min} < T\_t < T\_{max}
$$

$$
RH\_{min} < RH\_t < RH\_{max}
$$

#### 3.4.2 Particulate Matter

As documented in [QAN-001](https://zenodo.org/records/10688216), the particulate matter sensor is comprised of two separate components - a nephelometer and an optical particle counter (OPC). Several QA tests are performed on both individual components and the two components in complement.

**Laser Power**

The laser power of the OPC is checked to ensure it is within an acceptable operating range. Values for the acceptable operating range are based on years of data across thousands of devices as well as laboratory tests.

**Flow Rate**

The flow rate of air through the OPC is checked to ensure it is within an acceptable operating range.

**Errant Bin Counts**

The individual bin counts for each of the 24 OPC bins are checked to ensure they are below the overflow value. Additionally, an analysis is performed to ensure neighboring bins are within an expected range based on the value of counts in a specified bin.

For example, if there are 100 counts/cm3 in OPC bin 2, we ensure bins 1 and 3 look appropriate based on expected particle size distributions.

**Sensor** **Intercomparison**

For sub-micron particles, the values from both the OPC and nephelometer are checked against one another to ensure they fall within an appropriate range based on expected scattering patterns.

## 4. Maintenance and Service

There are no consumable or user-replaceable components to the MODULAIR-PM. If you believe a component is broken or not functioning correctly, please contact support via the in-app chat for the next steps.

### 4.1 Reporting Issues

As a new product, issues will likely arise with the hardware, firmware, software, or all three! We do our best to prevent issues from arising and will be timely in fixing any that do arise. If you experience an issue or have a suggestion related to the MODULAIR-PM hardware, please check the [knowledge base](https://support.quant-aq.com/). If you do not find the answer you're looking for in the [knowledge base](https://support.quant-aq.com/), you can open a ticket via the in-app chat.

## 5. Changelog

### 5.1 Hardware Changes

<table><thead><tr><th width="213">DATE</th><th width="134">VERSION</th><th>CHANGES</th></tr></thead><tbody><tr><td>July 2021</td><td>0.3.0</td><td><ul><li>Updated the Core Board to remove the external watchdog</li><li>de-populated components that were previously unused</li></ul></td></tr><tr><td>January 2021</td><td>0.2.0</td><td><ul><li>Removed the LED screen to mitigate issues and confusion around it being used for real-time information</li><li>Updated the enclosure to a new version due to supply chain issues</li><li>Introduced a new sheet-metal chassis</li></ul></td></tr></tbody></table>

### 5.2 Firmware Changes

For a full list of firmware changes, please visit our [public changelog](https://changes.quant-aq.com).

## 6. Appendix

### 6.1 Wiring Diagrams

All cables used in the MODULAIR-PM are manufactured by Molex and available via most major distributors including DigiKey, Mouser, and Newark. The following table lists the part numbers and cable lengths for the cable connector; exact pinout diagrams can be found in the following subsections. Where applicable, "NC" means not connected.

| CBL-1 | 8 | Molex | 530470810  | 304.8 |
| ----- | - | ----- | ---------- | ----- |
| CBL-2 | 4 | Molex | 530480410  | 304.8 |
| CBL-3 | 8 | Molex | 530470810  | 304.8 |
| CBL-4 | 6 | Molex | 5015680607 | 304.8 |

#### 6.1.1 CBL-1: µSD Breakout Board

CBL-1 connects the Core Board to the µSD Breakout Board.

| PIN NUMBER | LABEL | TYPE | DECRIPTION                   |
| ---------- | ----- | ---- | ---------------------------- |
| 1          | VCC   | PWR  | Power in; 4.2VDC (5.5V Max)  |
| 2          | EN    | IN   | LVO enable pin (active high) |
| 3          | CLK   | BD   | Serial Clock (SPI)           |
| 4          | MOSI  | BD   | Master out slave in (MOSI)   |
| 5          | CS    | IN   | Chip Select (SPI)            |
| 6          | MISO  | BD   | Master in slave out (SPI)    |
| 7          | NC    |      |                              |
| 8          | GND   | GND  | Ground                       |

#### 6.1.2 CBL-2: RHT Breakout Board

CBL-2 connects the Core Board to the Relative Humidity and Temperature board on the sampling manifold.

| PIN NUMBER | LABEL | TYPE | DECRIPTION              |
| ---------- | ----- | ---- | ----------------------- |
| 1          | VCC   | PWR  | Power in; 3.3V          |
| 2          | SDA   | DATA | Serial data line (I2C)  |
| 3          | SCL   | DATA | Serial clock line (I2C) |
| 8          | GND   | GND  | Ground                  |

#### 6.1.3: CBL-3: Particle Sensor 1

CBL-3 connects the Core Board to Particle Sensor 1.<br>

| PIN NUMBER | LABEL | TYPE | DECRIPTION         |
| ---------- | ----- | ---- | ------------------ |
| 1          | VCC   | PWR  | Power in; 5V       |
| 2          | GND   | GND  | Ground             |
| 3          | NC    |      |                    |
| 4          | NC    |      |                    |
| 5          | TXD   | DATA | Serial data (UART) |
| 6          | NC    |      |                    |
| 7          | NC    |      |                    |
| 8          | NC    |      |                    |

#### 6.1.4: CBL-4: Particle Sensor 2

CBL-4 connects the Core Board to Particle Sensor 2.

| PIN NUMBER | LABEL | TYPE | DECRIPTION                |
| ---------- | ----- | ---- | ------------------------- |
| 1          | VCC   | PWR  | Power in; 5V              |
| 2          | SS    | IN   | Chip select pin (SPI)     |
| 3          | MOSI  | DATA | Master out slave in (SPI) |
| 4          | MISO  | DATA | Master in slave out (SPI) |
| 5          | CLK   | DATA | Serial clock (SPI)        |
| 6          | GND   | GND  | Ground                    |

### 6.2 Status LED Meaning

The LED indicator on the front panel is used to communicate the status of the cellular and cloud communication status. The LED changes color and mode, each of which indicates a different state as outlined below. The rate at which the LED blinks comes in two flavors: blinking and breathing, where breathing implies a slow pulse where the color of the LED fades in and out.

<table><thead><tr><th width="143">LED COLOR</th><th width="113">BLINK PATTERN</th><th>MODE</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>Green</td><td>Blinking</td><td>Looking for internet</td><td>If your device is blinking green, it is trying to connect to the cellular network. There is no need to take any action.</td></tr><tr><td></td><td>Breathing</td><td>Cloud not connected</td><td>If your device is breathing green, it has a cellular connection but has not been able to connect to the cloud.</td></tr><tr><td>Cyan</td><td>Blinking</td><td>Connecting to the cloud</td><td>Blinking cyan indicates the device has a cellular connection and is attempting to connect to the cloud. There is no need to take any action. This will happen each time on device startup.</td></tr><tr><td></td><td>Breathing</td><td>Connected</td><td>When your device is breathing cyan, everything is good and you are happily connected to the internet and the QuantAQ Cloud.</td></tr><tr><td>Magenta</td><td>Blinking</td><td>Firmware Update</td><td>When your device is blinking magenta, it is undergoing an over-the-air firmware update. DO NOT power off when this is happening.</td></tr><tr><td>White</td><td>Breathing</td><td>Cellular Off</td><td>If the LED is breathing white, the cellular connection has been turned off. If you did not explicitly turn off the cellular connection via the on-board switch, please notify QuantAQ.</td></tr><tr><td>Red</td><td>Blinking</td><td>System Failure</td><td>A system failure has occurred. This is likely caused by faulty on-board firmware or corrupted memory. Please contact QuantAQ for next steps.</td></tr></tbody></table>


# Solar Power System

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>Solar Power System</td><td>This page covers our Solar Power System based on Lithium Ion chemistry</td><td></td><td><a href="/files/2jyI61EX8lLQr3MFrKFj">/files/2jyI61EX8lLQr3MFrKFj</a></td><td><a href="/pages/l7izKtEsNQUK6DRbjd6l">/pages/l7izKtEsNQUK6DRbjd6l</a></td></tr><tr><td>Smart Solar Power System</td><td></td><td>This page covers our Smart Solar Power System based on LiFePO4 chemistry</td><td><a href="/files/AIq2jZ93laIUnRnG9wgH">/files/AIq2jZ93laIUnRnG9wgH</a></td><td><a href="/pages/tNeiHXiiyTnTFKQdqwZu">/pages/tNeiHXiiyTnTFKQdqwZu</a></td></tr></tbody></table>


# Solar Power System (pre-2025)

Product manual for the MODULAIR Solar Power System (pre-2025).

<table><thead><tr><th width="184">KEY</th><th width="218">VALUE</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><strong>Product Name</strong></td><td>Solar Power System</td><td></td></tr><tr><td><strong>SKU(s)</strong></td><td>MOD-SOLAR-KIT</td><td>94Wh Li-Ion battery with 20W solar panel</td></tr></tbody></table>

## 1. Introduction and Specs

The MODULAIR Solar Power System is a plug-and-play solar power and battery combination that allows off-grid use of MODULAIR and MODULAIR-PM products.

{% hint style="warning" %}
This product is no longer manufactured or sold by QuantAQ as of November 2024. This manual is here for current customers and historical records only.
{% endhint %}

### 1.1 Specifications

<table><thead><tr><th width="254">PARAMETER</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><strong>Battery Capacity</strong></td><td>26,800 mAh, 94 Wh</td></tr><tr><td><strong>Battery Output</strong></td><td>5V, 2A</td></tr><tr><td><strong>Battery Type</strong></td><td>Lithium Ion</td></tr><tr><td><strong>Solar Panel</strong></td><td>20W, 6V</td></tr><tr><td><strong>Operating Range</strong></td><td>-15ºC to 60ºC<br><br>Safe charging range: 0ºC to 45ºC<br>Safe discharging range: -15ºC to 60ºC</td></tr></tbody></table>

### 1.2 Certifications

The underlying batteries (manufactured by Voltaic Systems, NY) are certified to:

* UN 38.3
* IEC 62133
* CE
* FCC

## 2. Installation and Hardware Setup

### 2.1 Required Tools

* [ ] Phillips Screwdriver
* [ ] Adjustable wrench

### 2.2 What's Included?

<table><thead><tr><th width="592">Item Description</th><th data-type="number">Quantity</th></tr></thead><tbody><tr><td>Battery in Hammond waterproof case</td><td>1</td></tr><tr><td>Solar Panel Mounting Bracket</td><td>1</td></tr><tr><td>Battery Box Mounting Bracket</td><td>1</td></tr><tr><td>4' Extension cable for solar panels</td><td>1</td></tr><tr><td>20W Solar Panel</td><td>1</td></tr><tr><td>8-32 Screw with Nut</td><td>4</td></tr><tr><td>ETFE Panel Screw and Nut Set</td><td>5</td></tr><tr><td>1.5" U-Bolt with Mounting Plate</td><td>2</td></tr><tr><td>1" U-Bolt with Mounting Plate</td><td>2</td></tr></tbody></table>

<figure><img src="/files/yUWEu8WbpVkBGRPiEhS5" alt=""><figcaption><p>Figure 2.1: All components included in the Solar Power System.</p></figcaption></figure>

### 2.3 Mounting Considerations

The Solar Power System includes 1" and 1.5" U-Bolts for mounting both the Battery Bracket and Solar Panel Bracket to a pole or post, but you can use whatever suits your specific mounting needs. The Solar Power System is designed to be mounted to a tripod or circular fence post but can be easily adapted for alternative installations.

It is important to ensure the orientation of the Solar Panel is optimal for your geographic location. If in the northern hemisphere, your panel should be installed facing true south, and if in the southern hemisphere, it should be mounted true north. The panel should be mounted at an angle of between 30 and 45 degrees to optimize charging.

As shipped, our Solar Panel System is optimized to be mounted of poles with diameters between 1.5” to 2.25”.

### 2.4 Installation

#### 2.4.1 Mount the Solar Panel to the Solar Panel Bracket

The first step is to mount the 20W solar panel to the Solar Panel Bracket. Remove the plastic covering from the face of the solar panel and align them so that five mounting holes align with the holes in the bracket. Use the panel mounting screws (Bag 2) to secure the solar panel to the bracket.

<figure><img src="/files/tVFcqKD13HFo881aD6jj" alt="" width="563"><figcaption><p>Figure 2.2: Mount the 20W Solar Panel to the Solar Panel Bracket using the ETFE screw set.</p></figcaption></figure>

#### 2.4.2 Mount the Battery to the Battery Bracket

Use the four 8-32 screws and nuts (Bag 1) to secure the battery box bracket to the battery box.

<figure><img src="/files/uc6i0HJwBE7dATlIVey0" alt="" width="563"><figcaption><p>Figure 2.3: Mount the Battery Box Bracket to the Battery Box using the 8-32 screws and nuts.</p></figcaption></figure>

#### 2.4.3 Attach the Solar Panel Cable

Attach the 4' extension cable and attach the end of the cable to the available power input connection on the left-hand side of the base of the Battery Box. At this point, the Solar Panel is connected to the Battery and is ready to mount. **Note: make sure the cable is fully inserted into its mate to ensure a good connection and to keep it waterproof.**

#### 2.4.4 Mount the Assembly

The final step is to mount the Solar Power System to a tripod, pole, or post. The 1" and 1.5" u-bolts provided in the shipment are one option. If these are not compatible with your specific mounting scenario, additional U-bolts or hose clamps should be obtained.

Reference the bracket dimensions in the Appendix to choose the best mounting hardware for your use case.

Upon mounting, orient the Solar Panel such that sun exposure is maximized (i.e. South facing if in the Northern Hemisphere). Double-check that the solar panel power cable connections are secure and connect the USB-C power cable on the right-hand side of the battery box to your MODULAIR or MODULAIR-PM system.

## 3. Appendix

### 3.1 Dimensions

#### 3.1.1 Solar Panel Bracket

The mounting area of the solar panel bracket is designed to fit as many possible mounting configurations as possible. Each slot is 10 mm in diameter and ranges from 21 mm to 29 mm in width from center to center. There are also two mounting holes for screws that are each 5 mm in diameter and located 38 mm apart from one another vertically. The two slots in the vertical center of the bracket are each 29 mm by 10 mm and fit U-bolts that can range from 27-85 mm in width. The four vertical slots are each 21 x 10 mm and are placed 75 mm apart horizontally and will fit U-bolts between 25 mm and 67 mm.

The technical drawing for this bracket can be found on the manufacturer’s website [here](https://voltaicsystems.com/content/Voltaic%20Systems%20Large%20Panel%20Bracket.pdf).

#### 3.1.2 Battery Pack Bracket

Dimensions for the battery bracket are in mm. There are three sets of mounting slots for the U-bolts and/or hose clamps to go through. They are centered at 1", 2", and 3.5" apart from one another. They are all 0.55" tall → hose clamps that have a width of 0.5" or less will easily fit.

<figure><img src="/files/OuJFp7ztAlZ4wqjJrwvm" alt=""><figcaption><p>Figure 3.1: Battery bracket dimensions.</p></figcaption></figure>


# Smart Solar Power System

This page includes the Smart Solar Power System operating manual.

<table><thead><tr><th width="165">KEY</th><th width="244">VALUE</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td><strong>Product Name</strong></td><td>Smart Solar Power System</td><td></td></tr><tr><td><strong>SKU(s)</strong></td><td>SOL-SM-V102-25W</td><td>18Ah LiFePO4 battery with 25W panel</td></tr><tr><td></td><td>SOL-SM-V102-50W</td><td>18Ah LiFePO4 battery with 50W panel</td></tr></tbody></table>

## 1. Introduction and Specs

### 1.1 Overview

The Smart Solar Power System is an easy-to-install, long-lasting solar power system with integrated data logging designed for QuantAQ's MOD-X series IoT air quality sensors. The system is pre-installed onto QuantAQ's Solar Pole Mount Kit, making installation easy. The battery uses long-life LiFePO4 (LFP) cells and an integrated MPPT charge controller. Battery and Solar Panel health can be monitored from within the QuantAQ Cloud on supported systems.

An optional 5V USB converter cable allows the Smart Solar Power System to be used with older QuantAQ air quality sensors.

{% hint style="info" %}
The data transmission is not supported when using the Smart Solar Power System with older QuantAQ sensors.
{% endhint %}

### 1.2 Specifications

**Battery**

| PARAMETER                         | VALUE                                                              |
| --------------------------------- | ------------------------------------------------------------------ |
| **Nominal Capacity**              | 18 Ah / 230 Wh                                                     |
| **Max Input Current**             | 10 A                                                               |
| **Cell Configuration**            | 4S 3P LFP 32700                                                    |
| **Mass**                          | 3 kg                                                               |
| **Input Connectors**              | MC4                                                                |
| **Standard Output Connector**     | M12, 4 pin                                                         |
| **Input Voltage Range**           | 14.5 V - 25 V                                                      |
| **Output Temperature Range**      | -20º - 60ºC                                                        |
| **Input Temperatute Range**       | 0º - 45ºC                                                          |
| **Standard Output Voltage Range** | 12.4 V - 14.6 V                                                    |
| **Protections**                   | Short Circuit, Over Discharge, Over Temperature, Under Temperature |
| **Certifications**                | CE, FCC, RoHS, UN 38.3                                             |

**Solar Panel**

The table below includes values for both the 25W and 50W SKUs. If different, the value for the 50W system will be listed after the "/".

| PARAMETER                   | VALUE           |
| --------------------------- | --------------- |
| Wp - Maximum Power          | 28.5 W / 56.7 W |
| Vp - Voltage at Max Power   | 17.7 V          |
| Voc - Open-Circuit Voltage  | 20.7 V          |
| Ip - Current at Max Power   | 1.53 A / 3.2 A  |
| Isc - Short-Circuit Current | 1.69 A / 3.37 A |
| Solar Cell Efficiency       | 22.8%           |
| Number of Cells             | 30              |
| Mass                        | 2 kg / 3.4 kg   |
| Connector Type              | MC4             |
| Temperature Range           | -40º - 85ºC     |

### 1.3 Certifications

Individual components of the battery assembly are certified by the battery vendor. The complete assembly is tested and certified to UN 38.3 and has a complete MSDS. The charge controller is tested and certified to EC62109, IEC62509, and CE. The LFP cells are tested and certified to UL1642.

### 1.4 Instrument Overview

**System Overview**

<figure><img src="/files/YIoiW9EbnCgAmnWbZYhs" alt=""><figcaption><p>Figure 1.1: A labeled diagram of the Smart Solar Power System.</p></figcaption></figure>

## 2. Installation and Hardware Setup

The Smart Solar Power System is shipped pre-assembled to ensure a quick and easy installation process. However, there are a few things to keep in mind:

* **Mounting Surface.** The Smart Solar Power System is designed to be mounted to poles or posts with clear access to sunlight. While it may be possible (use your discretion), we do not recommend installing on horizontal surfaces such as railings.
* **Orientation.** The azimuth and tilt angles at which the Solar Panel is installed are critically important for success and depend on your location and installation situation. We have resources for determining the ideal tilt and azimuth angle for your location ([see this link](https://footprinthero.com/solar-irradiance-calculator)) and season. If you have further questions, please contact support using the in-app chat. If you are installing in an area with obstructions (e.g., an urban canyon), you may need to take extra precautions when choosing an ideal installation setup.

{% hint style="info" %}
It is recommended that two people are present for the installation of the Smart Solar Power System, as the overall system weighs 17 lbs in total and \~9 lbs without the battery installed.
{% endhint %}

### 2.1 Unboxing

When your system arrives, it will be packaged in its shipping box, pre-assembled. Once the box is open and the cables and quick-start guide are removed from the top of the box, carefully remove the assembly from the box by lifting underneath the sides of the solar panel and lifting it straight up. Set the assembly aside and cut away the plastic wrapping holding it together. In the box, you should expect to find:

* Smart Solar Panel System Assembly
* Quick-Start Guide
* Parts bag including:
  * Four (4) 2.5" 1/4"-20 carriage bolts
  * Four (4) 1/4"-20 hex nuts
  * Two (2) Mounting Plates

To complete the installation, you will need the following tools:

* [ ] 7/16" socket or wrench

Please see the unboxing and installation video below for a complete walk-through:

{% embed url="<https://www.loom.com/share/4ce72967ec2e46068ae05413875c689a?sid=53927083-be34-4854-8caa-f7335449715e>" %}

### 2.2 Installation

{% stepper %}
{% step %}

### Remove the Battery Assembly and Screws

Lift the Solar Panel so that you can access the battery. At the base of the battery, there is a 1/4"-20 hex-head screw holding the battery into place. Remove the screw and set it aside.&#x20;

Near the top of the bracket, you will find two additional 1/4"-20 hex-head screws for securing the tilt angle of the solar panel. Remove those screws and set them aside.
{% endstep %}

{% step %}

### Secure the Solar Panel Assembly to the Pole or Post

If you are mounting to a pole that is <2" in diameter, you can use the provided mounting hardware for installation. If installing to a larger post, you will need to acquire your own mounting hardware that fits the post you are installing to. We recommend hose clamps or metal straps that are no larger than 0.5" wide.

**Mounting to a Pole < 2" in Diameter**

Pre-set two of the provided carriage bolts in the bracket as shown below:

<figure><img src="/files/LcWLXP3ob220ZewAjjPt" alt="" width="375"><figcaption></figcaption></figure>

With the help of a second installer, place the bracket assembly against the post and secure using one of the mounting plates and two of the hex-head nuts:

<figure><img src="/files/OKnrHxaskg5LMnFaeHgZ" alt="" width="375"><figcaption></figcaption></figure>

Make sure to tighten both nuts evenly to distribute the stress against the entire mounting plate. Once complete, repeat this step with the lower mounting plate.

**Mounting to a Post > 2" in Diameter**

If you are mounting to a larger post, please follow the instructions in the following video:

{% embed url="<https://www.loom.com/share/41b935cb618f41e08ba5cdbdc56f94c2?sid=dd3ddfde-01de-4412-93cf-35f2688643cf>" %}
{% endstep %}

{% step %}

### Set the Solar Panel Tilt Angle

Once the bracket assembly is installed, adjust the solar panel's tilt angle to the appropriate angle for your location and installation scenario. Secure in place using the two previously-removed 1/4"-20 hex-head screws.

<figure><img src="/files/2CJbozeac1q5X7hsITX2" alt="" width="375"><figcaption></figcaption></figure>

The tilt angles are labeled with each hole representing 10º in additional tilt. Once in place, ensure all four 1/4"-20 screws are tightened.
{% endstep %}

{% step %}

### Install the Battery Pack

Lift and set the battery pack into its slot by forcing against the back of the bracket's sheet metal and slowly lowering it into place, as shown below:

<figure><img src="/files/KcZ8qUhy038oKQw3FUPd" alt="" width="375"><figcaption></figcaption></figure>

Once the battery is safely in place, use the previously-removed 1/4"-20 hex-head screw to secure it in place.

<figure><img src="/files/grW7YyMP2wz6i08hYYfI" alt="" width="375"><figcaption></figcaption></figure>
{% endstep %}

{% step %}

### Connect and Secure the Cables

Attach the two MC4 cables (red and black) from the battery to the corresponding mating part on the Solar Panel:

<figure><img src="/files/qrVFHCZSfLcHbk0rJlK4" alt="" width="375"><figcaption></figcaption></figure>

Secure the cables in place using either a zip-tie or by slotting them into the cutouts in the bracket, as shown above. You may need to adjust the upper part of the cable by tugging it through the grommet near the top for a better fit.

At this point, the panel and battery are installed. However, the battery itself is not active until the M12 power output cable is connected, at which point the battery will become activated.&#x20;
{% endstep %}

{% step %}

### Plug in the Sensor

Plug the M12 power output cable into the base of your QuantAQ air quality sensor, which should natively accept the M12 connector. Plug in the M8 RS485 Communication cable between the battery and sensor, which provides data about the state of the battery and solar panel.

<figure><img src="/files/r9XrGfnvOqxsGnVve00m" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
**Using with USB-C Sensor Models**

If your QuantAQ air quality sensor has a 5V USB-C power input, you will need to use the 5V DC converter cable to interface with the Smart Solar Power System. Remove the protective sheet from the double-sided tape and secure the converter cable to the side of the battery. Plug the M12 cable into the M12 cable of the battery, and plug the USB-C cable into your sensor.<br>

More information can be found in Appendix 4.3 below.
{% endhint %}
{% endstep %}

{% step %}

### Verify your Installation

At the base of the battery pack, there is a series of three LEDs that indicate the operational status of the panel and battery. Complete documentation of the error codes can be found in Section 4.2. If you are installing the system while it's light out, you should expect to see the following:

* **Green**: either solid (System On, Not Charging) or flashing slowly (Charging)
* **Amber:** Solid (System On)
* **Red**: Off
  {% endstep %}
  {% endstepper %}

## 3. Maintenance

The frequency of maintenance for the Smart Solar Power System depends on your location and environment. We recommend the following maintenance schedule:

<table><thead><tr><th width="197">CHECK</th><th width="144">FREQUENCY</th><th>NOTES</th></tr></thead><tbody><tr><td>Manual Inspection</td><td>Quarterly</td><td>Inspect the system to ensure no cables are broken or damaged and the panel is intact (e.g., the glass isn't broken). If damage is present, please get in touch with support.</td></tr><tr><td>Panel Cleaning</td><td>Quarterly</td><td>Wipe down the Solar Panel with a damp cloth to remove any dust, dirt, or other debris.</td></tr></tbody></table>

## 4. Appendix

### 4.1 Dimensions

#### 4.1.1 Panel Dimensions

The bounding box for the 25W solar panel is 507 mm x 307 mm x 30 mm.

<figure><img src="/files/9HLjI4zgC1IxnLKD5yn1" alt="" width="563"><figcaption></figcaption></figure>

#### 4.1.2 Battery Dimensions

The bounding box for the battery is 100 mm x 237 mm x 104.2 mm.

<figure><img src="/files/RxIQrgJJwUDhmr3grA7o" alt=""><figcaption></figcaption></figure>

#### 4.1.3 Mounting Bracket Dimensions

<figure><img src="/files/uZkz2y9WyYvdKP8KZaXV" alt=""><figcaption></figcaption></figure>

### 4.2 LED Status Codes

The battery includes a 3-LED array indicating the solar power system's operational status.&#x20;

<table><thead><tr><th width="129">COLOR</th><th width="180">PATTERN</th><th>MEANING</th></tr></thead><tbody><tr><td>Green</td><td>Solid</td><td>System On, Not Charging</td></tr><tr><td></td><td>Flashing Slow</td><td>Charging</td></tr><tr><td></td><td>Flashing Fast</td><td>MPPT/Optimized Charging</td></tr><tr><td>Amber</td><td>Solid</td><td>System On</td></tr><tr><td></td><td>Flashing Slow</td><td>Low Battery Voltage</td></tr><tr><td></td><td>Flashing Fast</td><td>Low Battery Protection</td></tr><tr><td>Red</td><td>Solid</td><td>No Output</td></tr><tr><td></td><td>Flashing Slow</td><td>Over Temperature Protection</td></tr><tr><td></td><td>Flashing Fast</td><td>Short Circuit / Overload Protection</td></tr></tbody></table>

### 4.3 12V-5V Converter Usage and Installation

When using the Smart Solar Power System with an older QuantAQ sensor model (USB-C based), you will need to use the provided 12V-to-5V DC converter cable.

<div data-full-width="false"><figure><img src="/files/Penr3UI2uNEJWiBtsDMT" alt="" width="563"><figcaption></figcaption></figure></div>

To install, plug the M12 cable end of the converter cable into the M12 cable from the battery, and plug the USB-C end of the converter cable into the sensor. The converter has VHB double-sided tape on the back. To install, remove the tape backing and place it on the battery, ensuring the cables are pointed down to prevent potential water ingress.

## 5. Storage

If you are planning to store your Smart Solar Power System when not in use, please follow these guidelines:

* **Cables**. Unplug the MC4 cables from the solar panel and any output cables from the battery before storing. If you are using the 12V-to-5V converter, make sure this is unplugged during storage, as it will drain the battery. Verify all LEDs on the battery are off before storing.
* **Temperature**. Store the battery in a location that maintains a temperature between 20ºC and 35ºC (68ºF to 95ºF) and a humidity level between 45% and 85%.
* **Redeployment.** The battery will continue to drain while stored. Before redeploying, we recommend charging the battery to full capacity.

## Changelog

<table><thead><tr><th width="208">DATE</th><th>CHANGES</th></tr></thead><tbody><tr><td>January 1st, 2025</td><td>This is the first release of this document.</td></tr><tr><td>February 10th, 2026</td><td>Added images to clarify the RS485 communication cable and fixed spelling and grammar errors.</td></tr><tr><td>April 17th, 2026</td><td>Added storage instructions and Appendix 4.3.</td></tr></tbody></table>


# Weather Station

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>Gill GMX200</td><td><a href="/files/n08Iwa7iqC42FajBZCEs">/files/n08Iwa7iqC42FajBZCEs</a></td><td><a href="/pages/4iDeDVi4ORYn0JzRd9hY">/pages/4iDeDVi4ORYn0JzRd9hY</a></td></tr><tr><td>Gill GMX500</td><td><a href="/files/rTpvRQIr3at11RwO6yXc">/files/rTpvRQIr3at11RwO6yXc</a></td><td><a href="/pages/4iDeDVi4ORYn0JzRd9hY">/pages/4iDeDVi4ORYn0JzRd9hY</a></td></tr></tbody></table>


# Gill MaxiMet Weather Station

This page includes the operating manual for the Gill MaxiMet GMX200 and GMX500 weather stations.

<table><thead><tr><th width="175.48046875">Key</th><th width="195.89453125">Value</th><th>Description</th></tr></thead><tbody><tr><td><strong>Product Name</strong></td><td>Weather Station</td><td></td></tr><tr><td><strong>SKU(s)</strong></td><td><a href="https://gillinstruments.com/wp-content/uploads/2024/08/1957-004-MaxiMet-GMX200-issue-11.pdf">WS-GMX200</a></td><td>Gill's MaxiMet GMX200 compact weather station.</td></tr><tr><td></td><td><a href="https://gillinstruments.com/wp-content/uploads/2024/08/1957-008-MaxiMet-GMX500-issue-12.pdf">WS-GMX500</a></td><td>Gill's MaxiMet GMX500 compact weather station.</td></tr></tbody></table>

## 1. Introduction and Specs

### 1.1 Overview

QuantAQ supports the integration of Gill MaxiMet weather stations with MODULAIR (X-series) products. Gill MaxiMet sensors are robust and have no moving parts. The stations are directly integrated with MODULAIR for direct data communication and fully integrated into the QuantAQ Cloud.

QuantAQ currently supports two weather station models (GMX200, GMX500) as documented in the table at the top of this page. The GMX200 offers wind speed and wind direction measurements, whereas the GMX500 offers wind speed and wind direction as well as ambient temperature, pressure, and relative humidity.

Further details can be found in the [Gill MaxiMet product manual](https://gillinstruments.com/wp-content/uploads/2022/11/1957-PS-021-Maximet-Manual-Issue-8.pdf).

### 1.2 Specifications

#### 1.2.1 Measurements

<table><thead><tr><th width="203.32421875">Parameter</th><th width="126.66796875">Model<select multiple><option value="Od5J4Wn5VD1X" label="GMX200" color="blue"></option><option value="bqznU2jwyyah" label="GMX500" color="blue"></option></select></th><th width="172.54296875">Key</th><th>Value</th></tr></thead><tbody><tr><td><strong>Wind Speed</strong></td><td><span data-option="Od5J4Wn5VD1X">GMX200, </span><span data-option="bqznU2jwyyah">GMX500</span></td><td>Range</td><td>0-60 m/s</td></tr><tr><td></td><td></td><td>Accuracy</td><td>0-10 m/s       0.3 m/s RMSE<br>10-40 m/s     3% RMSE<br>40-60 m/s    5% RMSE</td></tr><tr><td></td><td></td><td>Resolution</td><td>0.01 m/s</td></tr><tr><td><strong>Wind Direction</strong></td><td><span data-option="Od5J4Wn5VD1X">GMX200, </span><span data-option="bqznU2jwyyah">GMX500</span></td><td>Range</td><td>0-360ºC</td></tr><tr><td></td><td></td><td>Accuracy</td><td>0.5 m/s - 40 m/s    ±3º<br>40 m/s - 60 m/s    ±5º</td></tr><tr><td></td><td></td><td>Resolution</td><td>1º</td></tr><tr><td><strong>Air Temperature</strong></td><td><span data-option="bqznU2jwyyah">GMX500</span></td><td>Range</td><td>-40ºC to +70ºC</td></tr><tr><td></td><td></td><td>Accuracy</td><td>±0.3º</td></tr><tr><td></td><td></td><td>Resolution</td><td>0.1ºC</td></tr><tr><td><strong>Relative Humidity</strong></td><td><span data-option="bqznU2jwyyah">GMX500</span></td><td>Range</td><td>0-100% RH</td></tr><tr><td></td><td></td><td>Accuracy</td><td>typically ±2% RH across full range</td></tr><tr><td></td><td></td><td>Resolution</td><td>0.1% RH</td></tr><tr><td><strong>Barometric Pressure</strong></td><td><span data-option="bqznU2jwyyah">GMX500</span></td><td>Range</td><td>300 - 1250 hPa</td></tr><tr><td></td><td></td><td>Accuracy</td><td>Absolute (typically) ±0.4hPa<br>Relative (typically) ±0.08 hPa</td></tr><tr><td></td><td></td><td>Resolution</td><td>0.1 hPa</td></tr></tbody></table>

#### 1.2.2 Electromechanical

| Parameter        | GMX200                  | GMX500                  |
| ---------------- | ----------------------- | ----------------------- |
| Input Voltage    | 5V                      | 5V                      |
| Construction     | UV stabilized plastic   | UV stabilized plastic   |
| Weight           | 0.5 kg                  | 0.7 kg                  |
| Connector Type   | 9-way clipper connector | 9-way clipper connector |
| Protection Class | IP66                    | IP66                    |
| Operating temp.  | -35ºC to 70ºC           | -35ºC to 70ºC           |

### 1.3 Certifications

Gill products carry FCC, CA, and CE certifications for the MaxiMet product line.

### 1.4 Instrument Overview

<figure><img src="/files/CsFKxVci6peNnm4AlTKe" alt=""><figcaption><p>Figure 1.1: A labeled diagram of the GMX500 weather station (WS-GMX500)</p></figcaption></figure>

## 2. Installation and Hardware Setup

The Weather Station is shipped partially pre-assembled to ensure a quick and easy installation process. However, there are a few things to keep in mind:

* **Siting.** Avoid turbulence caused by surrounding structures that will affect the measurement, such as trees, buildings, or even posts or poles. The exact location and manner in which you site your weather station depends on your constraints and measurement goals. Please see section 2.3 for more information and guidance.
* **Orientation.** The weather station should be mounted horizontally and vertically as level as possible.
* **Pole or Post Diameter.** The mounting bracket that ships with the weather station is designed to sit at the top of a pole or post with diameters between  1.5" and 2.5" in diameter. If this does not work for your use case, please contact QuantAQ Support for further information and drawings.

### 2.1 Unboxing

When your weather station arrives, it will be packaged in its shipping box, partially pre-assembled. Once the box is open, remove the mounting bracket, cable, and parts bag and set them aside. In the box, you should expect to find:

* Gill MaxiMet Weather Station (separately packaged within the box)
* Parts bag including:
  * Four (4) 1/4"-20 2.5" bolts
  * One (1) mounting back plate
  * Three (3) 10MM M5 screws
  * Three (3) M6 single-wave washers
* 9-pin clipper connector cable to 4P M12 cable
* Assembled mounting bracket and post

<figure><img src="/files/gq1Tj8RWrloOnDUdQLHD" alt=""><figcaption><p>Figure 2.1: Unboxing the Weather Station, you will find four items: (1) Gill MaxiMet weather station; (2) 2M, 9-pin cable; (3) parts bag; and (4) the pre-assembled mounting bracket and post.</p></figcaption></figure>

<figure><img src="/files/xviMvT36NOZ74jYFFABN" alt=""><figcaption><p>Figure 2.2: Unpackaging the parts bag, you will find: (1) 4 1/4"-20 2.5" bolts; (2) 3 10MM, M5 screws; (3) 3 M6 single wave washers; and (4) the mounting back plate.</p></figcaption></figure>

### 2.2 Installation

Tools required:

* Adjustable or 3/8" wrench or socket for the 1/4"-20 bolts
* 4MM hex driver to secure the mounting screws between the weather station and mounting post
* zip ties to secure the cable to the mounting bracket

{% stepper %}
{% step %}

### Connector Assembly

Connect the 9-pin clipper connector to the base of the MaxiMet weather station. To do so, align the 9-pins to the 9-pin connector on the base of the weather station and twist the top part of the clipper connector until it locks.

<figure><img src="/files/mBQfSYfQsO2Y0jkj4vaS" alt="" width="375"><figcaption><p>Figure 2.3: Connect the 9-pin connector to the weather station.</p></figcaption></figure>
{% endstep %}

{% step %}

### Weather Station Assembly

{% hint style="info" %}
This step can be done before or after mounting the bracket to the post or pole for final installation.
{% endhint %}

Once the cable is connected to the weather station, place the M12-end of the cable through the top of the mounting post, allowing the cable to drop through the bottom of the mounting post. Orient the weather station such that the three holes along the bottom of the weather station align with the three tapped holes in the mounting post. Secure the weather station using the three M5 screws and single-wave washers.&#x20;

Using a zip-tie or similar, secure the cable to the mounting bracket to provide strain relief.

<figure><img src="/files/KKVnCy3nfOHFCBLWzdvt" alt=""><figcaption><p>Figure 2.4: Provide strain relief to the cable using a zip-tie and the zip-tie slot of the mounting bracket.</p></figcaption></figure>
{% endstep %}

{% step %}

### Mounting

Using the four (4) 1/4"-20 bolts, secure the Back Plate to the main Bracket by tightening the four bolts evenly until the Bracket is secured. For recommendations on siting, please see Section 2.3. Directionality of the sensor does not matter.&#x20;

All supported MaxiMet weather stations contain a 2-axis flux gate compass. The internal compass electronically senses the horizontal component of Earth's magnetic field. Information from the compass is used to correct the wind direction in instances where the weather station is not aligned to North.
{% endstep %}

{% step %}

### Connect to MODULAIR

Connect the M12 end of the cable into the 4-pin, M12 connector on your MODULAIR, located on the right side of the base of the instrument.
{% endstep %}
{% endstepper %}

### 2.3 Siting

When siting an ultrasonic wind sensor, it is important to ensure that the location is free from obstructions such as trees, buildings, and other structures that might cause wind disturbances. The sensor should be positioned at a height that is representative of the area’s typical wind conditions. Proper alignment and leveling of the sensor will further enhance the accuracy of wind speed and direction measurements. By taking these factors into account, you can ensure that the ultrasonic wind sensor provides reliable data for meteorological analysis.

The World Meteorological Organization makes the following recommendations:

* The standard exposure of wind instruments over level open terrain is 10m above the ground. Open terrain is defined as an area where the distance between the sensor and any obstruction is at least 10 times the height of the obstruction.
* If mounting on a building, then theoretically the sensor should be mounted at a height of 1.5 times the height of the building.

While the above recommendations are worth considering, it is likely you will need to find a site and mounting strategy that is practical without perturbing your measurement too much. If you are mounting the weather station such that a pole extends beyond the height of the weather station, the boom (distance from the pole or post) should be at least twice as long as the diameter of the pole.

For further recommendations on siting weather stations, please see the following resources:

1. [Washington Department of Ecology Meteroological Monitoring Procedure](https://apps.ecology.wa.gov/publications/documents/0002003.pdf)


# MODULAIR-UFP

Product manual for the MODULAIR-UFP ultrafine particle monitor.

| Key              | Valu                                                                                  |                                                                                           |
| ---------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| **Product Name** | MODULAIR-UFP                                                                          |                                                                                           |
| **SKU(s)**       | MOD-UFP-NORAM                                                                         | For use in North America.                                                                 |
|                  | MOD-UFP-GLOBAL                                                                        | For use outside North America. Please contact QuantAQ Sales for specific country support. |
| **Datasheet**    | [Download](https://assets.quant-aq.com/downloads/spec-sheets/modulair-ufp.latest.pdf) |                                                                                           |

## 1. Introduction and Specs

The MODULAIR™-UFP provides real-time, direct measurement of total particle number concentration (\~5-3,000 nm), temperature, humidity,  pressure, wind direction, and wind speed in an easy-to-use, easy-to-deploy, internet-connected system.&#x20;

### 1.1 Specifications

#### 1.1.1 Air Quality Measurements

| PARAMETER                  | RANGE             | ACCURACY  |
| -------------------------- | ----------------- | --------- |
| Total Number Concentration | 0 to 100,000 p/cc | +/- 10%   |
| Temperature\*              | -40ºC to 70ºC     | +/- 0.3ºC |
| Relative Humidity          | 0 to 100%         | +/- 2%    |
| Pressure                   | 300 to 1,250 hPa  | 0.4 hPa   |
| Wind Direction             | 0 to 60 m/s       | 3% RMSE   |
| Wind Speed                 | 0º to 360º        | +/- 3º    |

\*This is the specification for the temperature measurement itself provided by the GMX500 weather station, **not** the safe operating temperature of the MODULAIR-UFP.

For more information on the operating principle of the CPC, please refer to [Hering et al, 2025](https://www.tandfonline.com/doi/10.1080/02786826.2025.2506707?url_ver=Z39.88-2003\&rfr_id=ori:rid:crossref.org\&rfr_dat=cr_pub%20%200pubmed).

#### 1.1.2 Power and Communications

<table><thead><tr><th width="218.46484375">PARAMETER</th><th>DETAILS</th></tr></thead><tbody><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f50b">🔋</span> <strong>Power</strong></td><td>12V<br>5W average consumption</td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f4f6">📶</span> <strong>Communication</strong></td><td><strong>North America</strong><br>LTE Cat M1 with 2G fallback<br>Wi-Fi (2.4GHz or 5GHz)<br><br><strong>EMEAA</strong><br>LTE CAT1 with 2G/3G fallback<br>Wi-Fi (2.4GHz or 5GHz)</td></tr><tr><td><span data-gb-custom-inline data-tag="emoji" data-code="1f4c8">📈</span> <strong>Data</strong></td><td>Web interface (quant-aq.com)<br>Programmatic access (QuantAQ API)<br>Local storage (16GB µSD card)</td></tr></tbody></table>

#### 1.1.3 Operating Specifications

<table><thead><tr><th width="260.83984375">PARAMETER</th><th>DETAILS</th></tr></thead><tbody><tr><td>Weatherproof rating</td><td>IP67</td></tr><tr><td>Operating temperature</td><td>5ºC to 45ºC*</td></tr><tr><td>Operating humidity</td><td>05 to 95%, non-condensing</td></tr><tr><td>Dimensions</td><td>25.34" x 10.6" x 5.22"</td></tr><tr><td>Weight</td><td>10 lbs (4.5 kg)</td></tr></tbody></table>

{% hint style="info" %}
It is important to note that using the MODULAIR-UFP without proper winterization can lead to permanent, irreversible damage. The MODULAIR-UFP uses water as its operating liquid, and the instrument can be damaged if water internal to the system freezes and expands.
{% endhint %}

### 1.2 Certifications

Coming soon.

## 2. Sensor Overview

### 2.1 Front View

Below is a front view of the MODULAIR-UFP. Air is pulled in through the inlet on the base of the unit (see 2.2 Base View for a more detailed view). The top of the unit features the Gill MaxiMet GMX500 weather station.

<figure><img src="/files/3mN61Ci2WuzIGX3ZI9rz" alt=""><figcaption><p>Figure 2.1. Front view of the MODULAIR-UFP.</p></figcaption></figure>

### 2.2 Base View

The base of the MODULAIR-UFP highlights the inlet (with insect screen installed) and the M12 Power Cable.

<figure><img src="/files/PMn4YkU0s78eK0ySdPiP" alt=""><figcaption><p>Figure 2.2. Base view of the MODULAIR-UFP.</p></figcaption></figure>

### 2.3 Internal View

#### 2.3.1 Sensor View

The internals of the MODULAIR-UFP can be accessed by opening the outer lid of the MODULAIR-UFP enclosure. Near the top (closest to the weather station, external), you will see the power switch, status LED, µUSB debugging port, and µSD card. On the right-hand side, you will see the condensation particle counter (CPC). On the left-hand side, you will see the water reservoir and the load cell. Near the bottom, you will see the purge port.

<figure><img src="/files/lYNWzWH2b4pzZ2vHuLuh" alt=""><figcaption><p>Figure 2.3. Internal sensor view of the MODULAIR-UFP.</p></figcaption></figure>

#### 2.3.2 Core Board

{% hint style="info" %}
Under normal operating circumstances, it should not be necessary to access the Core Board directly. You should only do so under the advisement of the QuantAQ Support team.
{% endhint %}

The Core Board is mounted to the main chassis internal to the MODULAIR-UFP. A top-down view can be seen in Figure 2.3, where the µSD card, debugging port, Status LED, and power switch are accessible.

<figure><img src="/files/6pbYrzMnHlnYPh9OHbpA" alt=""><figcaption><p>Figure 2.4. The Core Board that runs all MODULAIR-X series devices.</p></figcaption></figure>

## 3. Installation and Hardware Setup

### 3.1 Unpacking

Your MODULAIR-UFP arrives in a custom Seahorse shipping case that is designed to keep your MODULAIR-UFP safe during transport. It is essential that you keep this case as-is in the event you need to transport the MODULAIR-UFP or ship it back to QuantAQ for calibration or repair. For shipping purposes, with all components in place, the enclosure measures 31" x 21" x 11" and weighs 45 lb.

When unpacking your MODULAIR-UFP, you should expect to find the following:

* MODULAIR-UFP Ultrafine Particle Monitor
* Pole Mount Bracket
* Components Box
  * Device registration card
  * AC/DC 12VDC Power Brick
  * M12 Power Cable
  * 6 mL syringe
  * Pole Mount Components Bag
    * (2) Pole Mount Back Plates
    * (4) 1/4"-20, 3" Carriage Bolts
    * (4) 1/4"-20 nuts
    * (4) 10-32, 3/8" screws

<figure><img src="/files/JORpONeMNYOBTZMCtj4b" alt=""><figcaption><p>Figure 3.1. The MODULAIR-UFP is shipped in a custom Seahorse enclosure.</p></figcaption></figure>

In the cardboard components box (lower right of Figure 3.1), you will find the loose components, including the power cable, power brick, registration card, and liquid syringe. These components are shown in Figure 3.2.

<figure><img src="/files/ZOkx8ZnS5bBtoXYbO90F" alt=""><figcaption><p>Figure 3.2. The components found inside the Components Box.</p></figcaption></figure>

When removing the MODULAIR-UFP from its case, it is important not to lift by the Weather Station. This also applies when putting the MODULAIR-UFP back inside its case. Lift by either grabbing the sides of the polycarbonate enclosure or by the aluminum weather station mount, located between the polycarbonate enclosure and the weather station.

Once you remove the MODULAIR-UFP from its case, you will see a thin sheet of foam that sits below the sensor. After removing this layer of foam, you will find the Pole Mount Bracket. Please see Figure 3.3 for more instructions.

<figure><img src="/files/q9nkqXZpDPhnoEfsE9X7" alt=""><figcaption><p>Figure 3.3. Instructions for packing and unpacking the MODULAIR-UFP.</p></figcaption></figure>

A video overview of how to best pack and unpack your MODULAIR-UFP can be found below.

{% embed url="<https://www.loom.com/share/791028ef92914299815322cfde77d1d7>" %}

### 3.2 Device Registration

{% hint style="info" %}
You do not need to physically have your sensor present to complete the device registration process. The process can also be completed without powering on your sensor.
{% endhint %}

Each device ships with a **Registration Card** containing a QR code and a short confirmation code. Follow the instructions below to register your device.

{% stepper %}
{% step %}

### Scan the QR code

Using an internet-connected phone, tablet, or computer, scan the QR code on your Registration Card. It is best to first log in to quant-aq.com on the same device. The QR code should direct you to the registration page on the QuantAQ Cloud.
{% endstep %}

{% step %}

### Fill out the device registration form

Fill out the form presented to you on your screen.
{% endstep %}

{% step %}

### Enter the claim code

The form will ask you for a **Claim Code**, which can be found on your **Registration Card**. It is a 6-digit alphanumeric code. This ensures only the person in possession can register it.

Once completed, press "Register".
{% endstep %}
{% endstepper %}

### 3.3 Configuring Wi-Fi

{% hint style="warning" %}
Please note that configuring Wi-Fi is \*not\* required for operation. All MODULAIR devices have cellular modems, and Wi-Fi is a fallback in the event you are operating in an area that does not have a reliable cellular connection.
{% endhint %}

{% hint style="info" %}
To use our web-based configuration tool, you must use a computer operating system and browser that supports WebUSB technology. Examples include Chrome, Edge, and Opera browsers on Windows, Mac, Linux, or Chromebook devices.
{% endhint %}

To configure Wi-Fi credentials for your device, use our [web-based configuration tool](https://app.quant-aq.com/wifi-setup) or visit <https://app.quant-aq.com/wifi-setup>. Complete instructions can be found in our [Help Center](https://support.quant-aq.com/en/articles/10947910-configuring-wifi-credentials-on-supported-sensors). The MODULAIR can store up to ten separate credentials before they begin to be overwritten.&#x20;

### 3.4 Installation

{% hint style="info" %}
If the provided installation hardware does not work for your deployment, please contact QuantAQ Support via the in-app chat, and we will help to find a solution.
{% endhint %}

The MODULAIR-UFP ships with a Pole Mount Kit specifically designed to support the unit. It is designed to be attached to a pole or Post with a diameter between 1.25" and 2". The MODULAIR-UFP should be mounted toward the top of a pole or post such that the weather station is not impeded by anything and can provide accurate data (see Figure 3.4).&#x20;

<figure><img src="/files/p1GPlhCrfX02hQxwsUYW" alt="" width="375"><figcaption><p>Figure 3.4. An image of a well-installed MODULAIR-UFP instrument.</p></figcaption></figure>

To physically install your sensor, follow the instructions below.

{% embed url="<https://www.loom.com/share/ec4ae102c9c04965ada3f474842d75dd>" %}

{% stepper %}
{% step %}

#### Secure the Pole Mount Kit

Secure the Pole Mount Bracket to the pole using the included carriage bolts and back plates.

<figure><img src="/files/3Fwpf7i1Y707Pns0meBW" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Pre-install the 3/8" 10-32 screws to the MODULAIR-UFP

Using the provided 3/8", 10-32 screws, partially screw each one into the fasteners in each corner on the back of the MODULAIR-UFP.
{% endstep %}

{% step %}

#### Secure the MODULAIR-UFP

Slide the four screws through the slots on the Pole Mount Bracket and secure using a 1/8" driver.

<figure><img src="/files/ogJtLDwJQDWwggxwzF8f" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Install the Power Cable

Plug the M12 to USB-C power cable into the base of the MODULAIR-UFP.
{% endstep %}

{% step %}

#### Make sure the Insect Shield is Installed Properly

During shipping and installation, the insect shield can become wedged against the base of the MODULAIR-UFP. Make sure it is properly seated, approximately 1" away from the base of the Swagelok fitting. See the image below for an example of how it should be positioned. When seated properly, you will feel the internal o-ring slip into place.

<figure><img src="/files/SL1S3dIL0FUjraG2BYEU" alt=""><figcaption></figcaption></figure>
{% endstep %}

{% step %}

#### Fill the Water Reservoir

Disconnect the water line that runs from the CPC to the water reservoir by pressing the button on the front of the fitting attached to the lid of the water reservoir. Carefully remove the water reservoir from its cradle and fill it with up to 500 mL of distilled water (or cleaner). Reinsert the water reservoir by sliding it into the cradle, while pushing up on the cradle from underneath to prevent the load cell from being depressed too hard. Then, reattach the water line that connects the water reservoir to the CPC. A detailed view of this step can be seen in the video located in Section 3.5.1 below.
{% endstep %}

{% step %}

#### Purge the Water Line

Connect the provided 6 mL syringe to the Purge Port near the bottom of the MODULAIR-UFP. Extract water until there are no air bubbles remaining in the water line that connects the water reservoir to the CPC. This may take up to three pulls. Dispose of the water safely.
{% endstep %}

{% step %}

#### Power On the MODULAIR-UFP

Inside the MODULAIR-UFP, you will see the power switch toward the upper left-hand side. Slide the power switch to the right into the *on* position.

At this point, the Status LED will begin blinking, and within a few minutes, it should begin breathing cyan, which indicates it is connected to the internet and to the QuantAQ Cloud.
{% endstep %}
{% endstepper %}

### 3.5 Operation

#### 3.5.1 Refilling the Water Reservoir

The water reservoir holds up to 500 mL of distilled water. Under normal operating conditions, you should expect the water reservoir to last for \~120 days between refills. The video and instructions below cover how to refill the water reservoir.

{% embed url="<https://www.loom.com/share/bada9bad5c5548afb2cf9a260af13736>" %}

{% stepper %}
{% step %}

### Disconnect the water line

Disconnect the water line that runs from the CPC to the water reservoir by pressing the button on the front of the fitting attached to the lid of the water reservoir.&#x20;
{% endstep %}

{% step %}

### Remove the water reservoir

Carefully remove the water reservoir from its cradle by pulling it up and out toward you. You can use a second hand to hold the cradle in place or wiggle the reservoir back and forth if it is a tight fit.
{% endstep %}

{% step %}

### Refill the water reservoir

Fill the reservoir with up to 500 mL of distilled (or cleaner) water. When complete, reattach the lid of the Nalgene bottle.
{% endstep %}

{% step %}

### Reinstall the water reservoir

Reinsert the water reservoir by sliding it into the cradle, while pushing up on the cradle from underneath to prevent the load cell from being depressed too hard. Then, reattach the water line that connects the water reservoir to the CPC
{% endstep %}

{% step %}

### Purge the water line

Connect the provided 6 mL syringe to the Purge Port near the bottom of the MODULAIR-UFP. Extract water until there are no air bubbles remaining in the water line that connects the water reservoir to the CPC. This may take up to three pulls. Dispose of the water safely.
{% endstep %}
{% endstepper %}

#### 3.5.2 Storing or shipping your MODULAIR-UFP

Before storing or shipping your MODULAIR-UFP, it is important to ensure water is removed from the internals of the system to avoid breaking internal components. When water freezes, it expands, which can cause some internal subcomponents (e.g., the Nafion) to break. Before putting the MODULAIR-UFP in its shipping case, purge the water line several times as described in Step 6 of Section 3.5.1 above.&#x20;

### 3.6 Connectivity Considerations

As all QuantAQ products are internet-connected, it is important to consider connectivity when choosing an installation location. There are three primary things to consider:

1. **Antenna Connection.** If your device has an external antenna, ensure it is seated securely and placed at a 90º angle pointing toward the sky.
2. **Antenna Placement.** Do not place the device near metal objects or other sources of RF (i.e., antenna). Keep the antenna at least 18" away from metal objects as they can cause distortions and reflections.
3. **Location and Cellular Availability.** Install your sensor in a location with a known cellular signal on the carriers we support.

## 4. Software and Data

### 4.1 Data Structure and Outputs

There are three ways in which you can access data for the MODULAIR-UFP:

1. **Local Storage**. Raw, 10-second resolution data is available for download directly from the onboard 16GB µSD card.
2. **Web User Interface**. Data can be downloaded directly from the QuantAQ Cloud in CSV format.
3. **API.** Data can be accessed programmatically via the QuantAQ API.

#### 4.1.1 Local Storage

Data is collected and saved to an onboard µSD card every 10 seconds. Each minute, these values are averaged and pushed to the QuantAQ Cloud, where they are available for you to view, interact with, and download. It is unlikely you will ever *need* the locally stored data, but it is available to you if you would like to use it.

On the µSD card, you will find files with names like **DATA\_{YYYYMMDD}@FW{VERSION}.cs**v where **YYYYMMDD** represents the UTC date and **VERSION** represents the firmware version of the device. In the event a firmware update takes place mid-day, a new file will be created for that date.

<figure><img src="/files/YEa2SWO8QycQBORpsmZr" alt=""><figcaption><p>Figure 4.1. Sample of a data file header. The first three rows are metadata with subsequent rows containing the header and data.</p></figcaption></figure>

Data files are written each day and can be read or analyzed using any programming language or spreadsheet program (e.g., Microsoft Excel). Each file begins with three metadata rows describing the device model (row 1), device ID (row 2), and device serial number (row 3). Row 4 contains the data header columns, and rows 5 and higher contain data. Each row corresponds to a new record.

Table 4.1 below documents the columns available in the downloaded data, their units, and their description.

<table><thead><tr><th width="69.12890625" data-type="number">ID</th><th width="263.83984375">COLUMN</th><th width="115.78515625">UNIT</th><th>Description</th></tr></thead><tbody><tr><td>1</td><td>timestamp</td><td></td><td>Timestamp, UTC, ISO format</td></tr><tr><td>2</td><td>fw</td><td></td><td>Firmare version</td></tr><tr><td>3</td><td>flag</td><td></td><td>MODULAIR-UFP flag</td></tr><tr><td>4</td><td>soc</td><td>%</td><td>LiPo battery State of Charge</td></tr><tr><td>5</td><td>sample_temp</td><td>ºC</td><td>Internal box temperature</td></tr><tr><td>6</td><td>sample_rh</td><td>%</td><td>Internal box relative humidity</td></tr><tr><td>7</td><td>wx_ws</td><td>m/s</td><td>Vector Wind speed, as measured by the MaxiMet GMX500</td></tr><tr><td>8</td><td>wx_wd</td><td>deg</td><td>Vector Wind direction, as measured by the MaxiMet GMX500</td></tr><tr><td>9</td><td>wx_ws_scalar</td><td>m/s</td><td>Scalar wind speed, as measured by the MaxiMet GMX500</td></tr><tr><td>10</td><td>wx_u</td><td></td><td>The u-component of the wind speed/direction</td></tr><tr><td>11</td><td>wx_v</td><td></td><td>The v-component of the wind speed/direction</td></tr><tr><td>12</td><td>wx_pressure</td><td>hPa</td><td>Ambient pressure, as measured by the MaxiMet GMX500</td></tr><tr><td>13</td><td>wx_temp</td><td>ºC</td><td>Ambient temperature, as measured by the MaxiMet GMX500</td></tr><tr><td>14</td><td>wx_rh</td><td>%</td><td>Ambient relative humidity, as measured by the MaxiMet GMX500</td></tr><tr><td>15</td><td>wx_dew_point</td><td>ºC</td><td>Ambient dew point, as measured by the MaxiMet GMX500</td></tr><tr><td>16</td><td>cpc_elapsed_seconds</td><td>s</td><td>Seconds since the CPC started up.</td></tr><tr><td>17</td><td>cpc_serial_number</td><td></td><td>Serial Number of the CPC subcomponent.</td></tr><tr><td>18</td><td>cpc_particle_number_conc</td><td>p/cc</td><td>Raw particle number concentration</td></tr><tr><td>19</td><td>cpc_particle_number_conc_corr</td><td>p/cc</td><td>Particle number concentration with nominal correction for high concentrations.</td></tr><tr><td>20</td><td>cpc_sample_number</td><td></td><td>The sample number, auto-incrementing</td></tr><tr><td>21</td><td>cpc_flag</td><td></td><td>The current flag of the CPC subcomponent</td></tr><tr><td>22</td><td>cpc_pressure_at_beginning</td><td>hPa</td><td>Pressure reading in cell when particle counting begins</td></tr><tr><td>23</td><td>cpc_pressure_at_end</td><td>hPa</td><td>Pressure reading in cell when particle counting ends</td></tr><tr><td>24</td><td>cpc_pressure_ambient</td><td>hPa</td><td>Ambient pressure, as measured by the CPC subcomponent</td></tr><tr><td>25</td><td>cpc_temperature_ambient</td><td>ºC</td><td>Ambient temperature, as measured by the CPC subcomponent</td></tr><tr><td>26</td><td>cpc_temperature_at_input</td><td>ºC</td><td>Temperature at the CPC input valve</td></tr><tr><td>27</td><td>cpc_humidity_at_input</td><td>%</td><td>Relative humidity at the CPC input valve</td></tr><tr><td>28</td><td>cpc_dew_point_at_input</td><td>ºC</td><td>Dew point at CPC input valve</td></tr><tr><td>29</td><td>cpc_temperature_at_output</td><td>ºC</td><td>Temperature at the CPC output valve</td></tr><tr><td>30</td><td>cpc_humidity_at_output</td><td>%</td><td>Relative humidity at the CPC output valve</td></tr><tr><td>31</td><td>cpc_dew_point_at_output</td><td>ºC</td><td>Dew point at the CPC output valve</td></tr><tr><td>32</td><td>cpc_particle_count</td><td></td><td>Number of detected particles during the count interval</td></tr><tr><td>33</td><td>cpc_particle_count_corr</td><td></td><td>Dead-time corrected particle count</td></tr><tr><td>34</td><td>cpc_flush_time_ms</td><td>ms</td><td>Cell flush time</td></tr><tr><td>35</td><td>cpc_humidification_time_ms</td><td>ms</td><td>Cell humidification time</td></tr><tr><td>36</td><td>cpc_expansion_time_start</td><td></td><td>Time after start of expansion that counting starts</td></tr><tr><td>37</td><td>cpc_expansion_time_end</td><td></td><td>Time after start of expansion that counting ends</td></tr><tr><td>38</td><td>cpc_dead_time_corr_factor</td><td></td><td>Dead-time correction factor</td></tr><tr><td>39</td><td>cpc_power_to_pump</td><td>%</td><td>Power to the pump</td></tr><tr><td>40</td><td>cpc_k_factor</td><td></td><td>Conversion factor used to calculate the number concentration including cell volume and conversion of pressure reading into appropriate units</td></tr></tbody></table>

#### 4.1.2 Data Stored on the QuantAQ Cloud

Data are pushed to the QuantAQ Cloud with 1-minute time resolution and can be downloaded via the API or via the web app as a CSV. When downloading data, you can select whether you would like to download the *raw* data, *final* data, or *raw+final* data. Generally, the *final* data is what is desired, as it contains the final, cleaned data that is ready for analysis. The *raw* data is well-suited for researchers trying to investigate specific questions. When downloaded, the data is exported as a CSV and contains the following columns:

<table><thead><tr><th width="269.5703125">COLUMN</th><th>FILE LOCATION<select multiple><option value="tF9caryzs2xx" label="raw" color="blue"></option><option value="qLNP8iAUsBxM" label="final" color="blue"></option></select></th><th>UNIT</th><th>DESCRIPTIO</th></tr></thead><tbody><tr><td>timestamp</td><td><span data-option="tF9caryzs2xx">raw, </span><span data-option="qLNP8iAUsBxM">final</span></td><td></td><td></td></tr><tr><td>id</td><td><span data-option="tF9caryzs2xx">raw, </span><span data-option="qLNP8iAUsBxM">final</span></td><td></td><td></td></tr><tr><td>timestamp_local</td><td><span data-option="tF9caryzs2xx">raw, </span><span data-option="qLNP8iAUsBxM">final</span></td><td></td><td></td></tr><tr><td>sn</td><td><span data-option="tF9caryzs2xx">raw, </span><span data-option="qLNP8iAUsBxM">final</span></td><td></td><td></td></tr><tr><td>sample_rh</td><td><span data-option="tF9caryzs2xx">raw, </span><span data-option="qLNP8iAUsBxM">final</span></td><td>%</td><td></td></tr><tr><td>sample_temp</td><td><span data-option="tF9caryzs2xx">raw, </span><span data-option="qLNP8iAUsBxM">final</span></td><td>ºC</td><td></td></tr><tr><td>lat</td><td><span data-option="tF9caryzs2xx">raw, </span><span data-option="qLNP8iAUsBxM">final</span></td><td></td><td></td></tr><tr><td>lon</td><td><span data-option="tF9caryzs2xx">raw, </span><span data-option="qLNP8iAUsBxM">final</span></td><td></td><td></td></tr><tr><td>device_state</td><td><span data-option="tF9caryzs2xx">raw, </span><span data-option="qLNP8iAUsBxM">final</span></td><td></td><td></td></tr><tr><td>wx_ws</td><td><span data-option="tF9caryzs2xx">raw, </span><span data-option="qLNP8iAUsBxM">final</span></td><td></td><td></td></tr><tr><td>wx_wd</td><td><span data-option="tF9caryzs2xx">raw, </span><span data-option="qLNP8iAUsBxM">final</span></td><td></td><td></td></tr><tr><td>wx_ws_scalar</td><td><span data-option="tF9caryzs2xx">raw, </span><span data-option="qLNP8iAUsBxM">final</span></td><td></td><td></td></tr><tr><td>wx_u</td><td></td><td></td><td></td></tr><tr><td>wx_v</td><td></td><td></td><td></td></tr><tr><td>wx_pressure</td><td></td><td>hPa</td><td></td></tr><tr><td>wx_temp</td><td></td><td>ºC</td><td></td></tr><tr><td>wx_rh</td><td></td><td>%</td><td></td></tr><tr><td>wx_dew_point</td><td></td><td>ºC</td><td></td></tr><tr><td>cpc_elapsed_seconds</td><td></td><td></td><td></td></tr><tr><td>cpc_serial_number</td><td></td><td></td><td></td></tr><tr><td>cpc_flag</td><td></td><td></td><td></td></tr><tr><td>cpc_pressure_at_beginning</td><td></td><td>hPa</td><td></td></tr><tr><td>cpc_pressure_at_end</td><td></td><td>hPa</td><td></td></tr><tr><td>cpc_pressure_ambient</td><td></td><td>hPa</td><td></td></tr><tr><td>cpc_temperature_ambient</td><td></td><td>ºC</td><td></td></tr><tr><td>cpc_temperature_at_input</td><td></td><td>ºC</td><td></td></tr><tr><td>cpc_temperature_at_output</td><td></td><td>ºC</td><td></td></tr><tr><td>cpc_humidity_at_input</td><td></td><td>%</td><td></td></tr><tr><td>cpc_humidity_at_output</td><td></td><td>%</td><td></td></tr><tr><td>cpc_dew_point_at_input</td><td></td><td>ºC</td><td></td></tr><tr><td>cpc_dew_point_at_output</td><td></td><td>ºC</td><td></td></tr><tr><td>cpc_particle_count</td><td></td><td></td><td></td></tr><tr><td>cpc_particle_count_corr</td><td></td><td></td><td></td></tr><tr><td>cpc_particle_number_conc</td><td></td><td></td><td></td></tr><tr><td>cpc_flush_time_ms</td><td></td><td></td><td></td></tr><tr><td>cpc_humidification_time_ms</td><td></td><td></td><td></td></tr><tr><td>cpc_expansion_time_start</td><td></td><td></td><td></td></tr><tr><td>cpc_expansion_time_end</td><td></td><td></td><td></td></tr><tr><td>cpc_dead_time_corr_factor</td><td></td><td></td><td></td></tr><tr><td>cpc_power_to_pump</td><td></td><td></td><td></td></tr><tr><td>cpc_k_factor</td><td></td><td></td><td></td></tr><tr><td>cpc_particle_number_conc_corr</td><td><span data-option="qLNP8iAUsBxM">final</span></td><td>p/cc</td><td></td></tr></tbody></table>

#### 4.1.3 Data Downloaded via API

For details on how to use the API to download data, please view the API docs [here](/software-apis-and-libraries/quantaq-cloud-api). The names, units, and descriptions for key-value pairs retrieved via the API are identical to those found in the section above, though they may be embedded beneath a key (e.g., all meteorological data is shown under the **met** key). Data is returned as JSON, as shown in the example below:

```json
// Some code
{
  "data": [
    {
      "cpc_particle_number_conc_corr": 54960,
      "geo": {
        "lat": null,
        "lon": null
      },
      "met": {
        "wx_dew_point": 14.37,
        "wx_pressure": 1011.68,
        "wx_rh": 39.43,
        "wx_temp": 29.6,
        "wx_u": -0.309,
        "wx_v": 2.256,
        "wx_wd": 352.21,
        "wx_ws": 2.28,
        "wx_ws_scalar": 2.35
      },
      "raw_data_id": 1,
      "sn": "MOD-UFP-00003",
      "timestamp": "2025-06-12T23:36:45",
      "timestamp_local": "2025-06-12T19:36:45",
      "url": "https://api.quant-aq.com/v1/devices/MOD-UFP-00003/data/1"
    },
    ...
  ],
  "meta": {
    "first_url": "https://api.quant-aq.com/device-api/v1/devices/MOD-UFP-00003/data/?page=1&per_page=50&limit=3",
    "last_url": "https://api.quant-aq.com/device-api/v1/devices/MOD-UFP-00003/data/?page=1&per_page=50&limit=3",
    "next_url": null,
    "page": 1,
    "pages": 1,
    "per_page": 50,
    "prev_url": null,
    "total": 3
  }
}
```

### 4.2 Understanding the Status Flag

Each record contains a status flag, stored as an unsigned integer, that describes the state of the device for that exact record. Flags contain encoded information about each of the sub-components onboard the device. They are generated via a bitmask and can be decoded by reversing the procedure. To determine whether a specific flag is set, you can use the bitwise AND operator. If the value of the flag is returned, then the flag is set. If a zero is returned, the flag is *not* set.&#x20;

To make this a bit clearer, let's follow this example. Let's assume the value of the flag is set to "4". We can perform a bitwise AND operation to check the result to see if FLAG\_STARTUP is set.

```
# bit AND - is FLAG_STARTUP set?
>>> 4 & 1
0

# bit AND - is FLAG_NEPH set?
>>> 4 & 4
4
```

The table below describes the available flags, flag values, and a description of what they mean and what action should be taken when they are set.&#x20;

{% hint style="info" %}
Flags are consistent across all QuantAQ products, so there may be flags in the table below that irrelevant to your product.
{% endhint %}

<table><thead><tr><th width="169.62109375">FLAG</th><th width="90.24609375">VALUE</th><th width="221.5234375">WHY IS IT SET?</th><th>WHAT TO DO?</th></tr></thead><tbody><tr><td>FLAG_STARTUP</td><td>1</td><td>This flag is set when the device powers on.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_OPC</td><td>2</td><td>This flag is set when the OPC has indicated the data failed to transfer correctly. This can be caused by the fan being off, the laser being off, or the checksum not validating properly.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_NEPH</td><td>4</td><td>This flag is set when the nephelometer has indicated the data failed to transfer correctly.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_RHTP</td><td>8</td><td>This flag is set when the relative humidity and temperature sensor has failed.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_CO</td><td>16</td><td>This flag is set when the CO sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_NO</td><td>32</td><td>This flag is set when the NO sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_NO2</td><td>64</td><td>This flag is set when the NO2 sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_O3</td><td>128</td><td>This flag is set when the O3 sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_CO2</td><td>256</td><td>This flag is set when the CO2 sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_SO2</td><td>512</td><td>This flag is set when the SO2 sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_H2S</td><td>1024</td><td>This flag is set when the H2S sensor has failed or data does not meet initial on-board QA/QC.</td><td>Remove any rows where this flag is set.</td></tr><tr><td>FLAG_BAT</td><td>2048</td><td>This flag is set when the internal LiPo battery is low or dead.</td><td>None.</td></tr><tr><td>FLAG_OVERHEAT</td><td>4096</td><td>This flag is set when the OPC has overheated.</td><td>Contact QuantAQ.</td></tr><tr><td>FLAG_SD</td><td>8192</td><td>This flag is set when the SD card has failed.</td><td>Replace the SD card.</td></tr></tbody></table>

## 5. Maintenance and Service

Coming soon.

## 6. Changelog

Please see our [public changelog](https://changes.quant-aq.com/) for a full history of all firmware changes.

## 7. Appendix

### 7.1 Status LED

The Status LED on the front panel is used to communicate the status of the internet connection. The LED changes color and pattern, each of which indicates a different state as outlined below. The rate at which the LED blinks comes in two flavors: *blinking* and *breathing,* where breathing implies a slow pulse where the color of the LED fades in and out.

<table><thead><tr><th width="143.58984375">LED COLOR</th><th width="97.0703125">PATTERN</th><th width="167.98046875">MODE</th><th>DESCRIPTION</th></tr></thead><tbody><tr><td>Green</td><td>Blinking</td><td>Looking for Internet</td><td>If your device is blinking green, it is trying to connect to the cellular network. There is no need to take any action.</td></tr><tr><td></td><td>Breathing</td><td>Cloud not Connected</td><td>If your device is breathing green, it has a cellular connection but has not been able to connect to the cloud.</td></tr><tr><td>Cyan</td><td>Blinking</td><td>Connecting to the Cloud</td><td>Blinking cyan indicates the device has a cellular connection and is attempting to connect to the cloud. There is no need to take any action. This will happen each time on device startup.</td></tr><tr><td></td><td>Breathing</td><td>Connected</td><td>When your device is breathing cyan, everything is good and you are happily connected to the internet and the QuantAQ Cloud.</td></tr><tr><td>Magenta</td><td>Blinking</td><td>Firmware Update</td><td>When your device is blinking magenta, it is undergoing an over-the-air firmware update. DO NOT power off when this is happening.</td></tr><tr><td>White</td><td>Breathing</td><td>Internet Off</td><td>If the LED is breathing white, the cellular connection has been turned off. If you did not explicitly turn off the cellular connection via the onboard switch, please notify QuantAQ.</td></tr><tr><td>Red</td><td>Blinking</td><td>System Failure</td><td>A system failure has occurred. This is likely caused by faulty on-board firmware or corrupted memory. Please contact QuantAQ for next steps.</td></tr></tbody></table>


# QuantAQ Cloud API

The QuantAQ Cloud API allows you to manage your air quality sensors and data in a simple, programmatic way using conventional HTTP requests. Each endpoint is intuitive and allows you to obtain data and execute various actions easily. If you notice something that can be made more clear or more intuitive, please let us know!

This documentation will begin with a general overview of the API and how it works, followed by details on each endpoint that is available in \*v1\* of the API. Throughout this documentation, there will be code examples using [httpie](https://httpie.org/) - an easy-to-use command-line client for making HTTP requests. The names of specific resources will be represented by variables, which are wrapped in "<>".

## Getting Started

### Obtaining an API key

Authentication is handled using HTTP Basic Auth, which consists of sending an API key that is unique to your account with each request. This key should be kept secret and not shared with anyone. This API key is tied to your user account and will only allow you to take actions within your assigned scope of permissions.

You can generate an API key for your account by visiting the **Developer** section within the QuantAQ Cloud and clicking **Generate New Key** in the upper right-hand corner of your screen. It is recommended that you set this key as an environment variable on your computer with the name **QUANTAQ\_APIKEY**.

To include your API key in your request, add an HTTP Authorization header, consisting of a `username`and `password.` When using **httpie**, you can use the `-a`flag to indicate authorization. The API key serves as the username, and the password should be left blank.

### Sending your first API call

To make an API call, you need four pieces of information:

1. `api_key`: a random string of alphanumeric characters that gives you access to the API
2. `endpoint`: the URI listed in the API reference section below
3. `method`: one of **GET**, **POST**, **PUT**, or **DELETE**
4. `arguments`: JSON-encoded values sent to the method (these are not *always* required)

More often than not, you will be sending either **GET** or **POST** requests to `api.quant-aq.com`. All API endpoints begin with the same URL, which, for the QuantAQ Cloud, is `api.quant-aq.com/`. The full URL will be of the form:

```sh
https://api.quant-aq.com/{version}/{endpoint}
```

The `version` of the API may change (this will be documented), which signals changes in the underlying structure of the API. For now, there is only one version available: `v1`. Throughout these docs, we will just assume the version is `v1`.

A good first API call would be to get your account information. As mentioned above, we will be using **httpie** for examples. To get your account information, the API call would look like:

```sh
$ http -a <your-api-key-here>: GET \
        https://api.quant-aq.com/v1/account
```

You should see a response that looks something like the following:

```json
{
    "confirmed": true,
    "email": "users_email@quant-aq.com",
    "first_name": "First Name",
    "id": 1,
    "is_administrator": false,
    "last_name": "Last Name",
    "last_seen": "2020-09-28T13:12:33.745041",
    "member_since": "2020-06-05T22:05:24.612347",
    "role": 5,
    "username": "username"
}
```

### Understanding API calls and responses

Any tool that is fluent in HTTP requests and supports HTTP basic authentication protocols can be used to communicate with the QuantAQ Cloud API. Requests must be made using HTTPS. The interface response depends on the action required.

#### HTTP statuses and errors

Each request that is made to the API will have an attached status code that tells you whether the request was successful or not. If there is an issue with the request, an error will be returned as indicated by both the HTTP status code and the response body. In general, if the status code is in the 200's, the request was successful. If the status code is in the 400's, there was an error with the request; this could range from improper authentication to an illegal operation (e.g., you were trying to request data for which you do not have the necessary permissions). If a 500 error is returned, there was a server-side error, which means we were unable to process the request for some reason.

An example error response:

```sh
HTTP/1.1 403 Forbidden
{
    "id": "forbidden",
    "message": "You do not have permissions for this action."
}
```

#### Rate Limiting

Rate limiting is set for the API at 150 requests/minute for all data endpoints. If you have exceeded this limit, you will receive a 429 status code and will need to wait until the next minute to make more requests.

***

## API Reference

### Account

This is an object representing your account information. You can retrieve it to see basic information about your account, as summarized in the *attributes* section below.

#### Get your account information

<mark style="color:green;">`GET`</mark> `/v1/account`

Retrieves the current account information for the user who is making the request.

<mark style="color:blue;">**Path Parameters**</mark>

None.

<mark style="color:blue;">**Query Parameters**</mark>

None.

<mark style="color:blue;">**Response**</mark>

*Body*

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>username</code></td><td>string</td><td>The accounts username</td></tr><tr><td><code>confirmed</code></td><td>boolean</td><td>True if the account user has confirmed their email address</td></tr><tr><td><code>email</code></td><td>string</td><td>The email address of record for the user</td></tr><tr><td><code>first_name</code></td><td>string</td><td>The first name of the account user</td></tr><tr><td><code>last_name</code></td><td>string</td><td>The last name of the account user</td></tr><tr><td><code>id</code></td><td>int</td><td>The unique identifier for the account user</td></tr><tr><td><code>last_seen</code></td><td>datetime</td><td>The last time the account user was seen</td></tr><tr><td><code>member_since</code></td><td>datetime</td><td>The timestamp corresponding to when the user joined the site</td></tr></tbody></table>

{% tabs %}
{% tab title="200" %}

```json
{
    "confirmed": true,
    "email": "your-email@email.com",
    "first_name": "First Name",
    "id": 1,
    "last_name": "Last Name",
    "last_seen": "2020-09-28T13:12:33.745041",
    "member_since": "2020-06-05T22:05:24.612347",
    "role": 5,
    "username": "username"
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

***

### Devices

This is an object representing a QuantAQ device. You can retrieve device information, either on an individual sensor basis or as a list to see basic information about the device(s), as summarized in the *attributes* section below. You can also update the information for a single device or delete a device.

#### Get a single Device

<mark style="color:green;">`GET`</mark> `/v1/devices/{serial_number}`

Retrieves the information for a single device by its serial number.

<mark style="color:blue;">**Path Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>serial_number</code></td><td>string</td><td>The serial number of the device</td></tr></tbody></table>

<mark style="color:blue;">**Query Parameters**</mark>

None.

<mark style="color:blue;">**Response**</mark>

*Body*

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>city</code></td><td>string</td><td>The city in which the device is installed</td></tr><tr><td><code>country</code></td><td>string</td><td>2-digit ISO country code corresponding to the country where the device is installed</td></tr><tr><td><code>created</code></td><td>datetime</td><td>The timestamp corresponding to when the device was brought online</td></tr><tr><td><code>description</code></td><td>string</td><td>The user-defined device description</td></tr><tr><td><code>geo.lat</code></td><td>float</td><td>The latitude corresponding to the geolocation of the device</td></tr><tr><td><code>geo.lon</code></td><td>float</td><td>The longitude corresponding to the geolocation of the device</td></tr><tr><td><code>id</code></td><td>int</td><td>The unique identifier for the device</td></tr><tr><td><code>model</code></td><td>string</td><td>The device model: one of [ <strong>modulair</strong>, <strong>modulair_pm, arisense_v200</strong> ]</td></tr><tr><td><code>last_seen</code></td><td>datetime</td><td>The last time the device was seen</td></tr><tr><td><code>n_datapoints</code></td><td>int</td><td><p>The total number of data points the device has collected over its lifetime</p><p></p><p>*no longer valid</p></td></tr><tr><td><code>owner_id</code></td><td>int</td><td>The id of the device owner</td></tr><tr><td><code>private</code></td><td>boolean</td><td>True if the device is marked as <strong>private</strong> by the device owner</td></tr><tr><td><code>sn</code></td><td>string</td><td>The serial number of the device</td></tr><tr><td><code>status</code></td><td>string</td><td>The current operation status of the device. One of: [ <strong>CALIBRATION</strong>, <strong>ACTIVE</strong>, <strong>RETIRED</strong>, <strong>PRE_REGISTERED</strong> ]</td></tr><tr><td><code>timezone</code></td><td>string</td><td>The timezone corresponding to the location where the device is installed</td></tr><tr><td><code>url</code></td><td>string</td><td>The url corresponding to the device</td></tr></tbody></table>

{% tabs %}
{% tab title="200" %}

```json
{
  "city": "Boston",
  "country": null,
  "created": "2019-12-08T23:23:28.107099",
  "description": null,
  "geo": {
      "lat": null,
      "lon": null
  },
  "id": 6,
  "last_seen": "2019-12-08T23:23:28.107106",
  "model": "arisense_v200",
  "n_datapoints": 0,
  "outdoors": true,
  "owner_id": 1,
  "private": true,
  "sn": "a123456",
  "status": "INACTIVE",
  "timezone": null,
  "url": "https://api.quant-aq.com/device-api/v1/devices/a123456"
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

#### Get a list of Devices

<mark style="color:green;">`GET`</mark> `/v1/devices`

Retrieves a paginated list of devices including all devices the user has access to across Organizations and Networks. If no Devices are available, an empty list will be returned.

<mark style="color:blue;">**Path Parameters**</mark>

None.

<mark style="color:blue;">**Query Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>org_id</code></td><td>int, optional</td><td>The ID of the Organization to subquery</td></tr><tr><td><code>network_id</code></td><td>int, optional</td><td>The ID of the Network to subquery</td></tr><tr><td><code>per_page</code></td><td>int</td><td>The number of items to return per page (default=50)</td></tr><tr><td><code>page</code></td><td>int</td><td>The page number to return (default=1)</td></tr><tr><td><code>sort</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>filter</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>limit</code></td><td>int, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr></tbody></table>

<mark style="color:blue;">**Response**</mark>

*Body*

Please see the table in the [previous section](#get-a-single-device) for detailed body information.

*Meta*

<table><thead><tr><th width="217">Name</th><th width="134">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>first_url</code></td><td>string</td><td>The url of the first page in the collection</td></tr><tr><td><code>last_url</code></td><td>string</td><td>The url of the last page in the collection</td></tr><tr><td><code>next_url</code></td><td>string</td><td>The url of the next page in the collection</td></tr><tr><td><code>prev_url</code></td><td>string</td><td>The url of the previous url in the collection</td></tr><tr><td><code>page</code></td><td>int</td><td>The current page number</td></tr><tr><td><code>pages</code></td><td>int</td><td>The total number of pages available</td></tr><tr><td><code>per_page</code></td><td>int</td><td>The number of records returned per page</td></tr><tr><td><code>total</code></td><td>int</td><td>The total number of records available in the query</td></tr></tbody></table>

{% tabs %}
{% tab title="200" %}

```json
{
  "data": [
      {
          "city": "New City",
          "country": "US",
          "created": "2019-03-03T17:50:16.829776",
          "description": "",
          "geo": {
              "lat": 42.5,
              "lon": -71.1
          },
          "id": 1,
          "last_seen": "2019-12-06T22:57:05.917175",
          "model": "arisense_v200",
          "n_datapoints": 4048,
          "outdoors": true,
          "owner_id": 1,
          "private": true,
          "sn": "SN000-001",
          "status": "CALIBRATION",
          "timezone": "US/Eastern",
          "url": "https://api.quant-aq.com/device-api/v1/devices/SN000-001"
      },
      ...
  ],
  "meta": {
      "first_url": "https://api.quant-aq.com/device-api/v1/devices/?page=1&per_page=50",
      "last_url": "https://api.quant-aq.com/device-api/v1/devices/?page=1&per_page=50",
      "next_url": null,
      "page": 1,
      "pages": 1,
      "per_page": 50,
      "prev_url": null,
      "total": 3
	}
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

#### Update a Device

<mark style="color:green;">`PUT`</mark> `/v1/devices/{serial_number}`

Retrieves the information for a single device by its serial number.

<mark style="color:blue;">**Path Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>serial_number</code></td><td>string</td><td>The serial number of the device</td></tr></tbody></table>

<mark style="color:blue;">**Query Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>city</code></td><td>string</td><td>The city in which the device is installed</td></tr><tr><td><code>country</code></td><td>string</td><td>2-digit ISO country code corresponding to the country where the device is installed</td></tr><tr><td><code>description</code></td><td>string</td><td>The user-defined device description</td></tr><tr><td><code>lat</code></td><td>float</td><td>The latitude corresponding to the geolocation of the device</td></tr><tr><td><code>lon</code></td><td>float</td><td>The longitude corresponding to the geolocation of the device</td></tr><tr><td><code>is_private</code></td><td>boolean</td><td>True if the device is marked as <strong>private</strong> by the device owner</td></tr><tr><td><code>device_state</code></td><td>string</td><td>The current operation status of the device. One of: [ <strong>CALIBRATION</strong>, <strong>ACTIVE</strong>, <strong>RETIRED</strong>, <strong>PRE_REGISTERED</strong> ]</td></tr><tr><td><code>timezone</code></td><td>string</td><td>The timezone corresponding to the location where the device is installed</td></tr></tbody></table>

<mark style="color:blue;">**Response**</mark>

*Body*

Please see the table in the [previous section](#get-a-single-device) for detailed body information.

{% tabs %}
{% tab title="200" %}

```json
{
  "city": "Boston",
  "country": null,
  "created": "2019-12-08T23:23:28.107099",
  "description": null,
  "geo": {
      "lat": null,
      "lon": null
  },
  "id": 6,
  "last_seen": "2019-12-08T23:23:28.107106",
  "model": "arisense_v200",
  "n_datapoints": 0,
  "outdoors": true,
  "owner_id": 1,
  "private": true,
  "sn": "a123456",
  "status": "INACTIVE",
  "timezone": null,
  "url": "https://api.quant-aq.com/device-api/v1/devices/a123456"
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

***

### Organizations

This is an object representing an *Organization*. You can retrieve it to see basic information about a given Organization including the members and devices, as summarized in the *attributes* section below.

#### Get a single Organization

<mark style="color:green;">`GET`</mark> `/v1/orgs/{org_id}`

Retrieve the information for a single Organization by its Organization ID. The user must be a confirmed member of the Organization, or the endpoint will return a 403.

<mark style="color:blue;">**Path Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>org_id</code></td><td>int</td><td>The ID of the Organization</td></tr></tbody></table>

<mark style="color:blue;">**Query Parameters**</mark>

None.

<mark style="color:blue;">**Response**</mark>

*Body*

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>name</code></td><td>string</td><td>The name of the Organization</td></tr><tr><td><code>id</code></td><td>string</td><td>The unique identifier for the Organization</td></tr><tr><td><code>description</code></td><td>string</td><td>A short description of the Organization</td></tr><tr><td><code>created_on</code></td><td>datetime</td><td>An ISO-formatted timestamp representing the creation date of the Organization</td></tr><tr><td><code>sandbox</code></td><td>boolean</td><td><em>true</em> if a Sandbox Organization, otherwise <em>false</em></td></tr><tr><td><code>members</code></td><td>list</td><td>A list containing the confirmed members of the Organization that are visible to the requesting user. Organization administrators can see all Organization members. Each entry is a sub-object representing an Organization user including their role and username.</td></tr><tr><td><code>devices</code></td><td>list</td><td>A list containing the serial number of all Devices associated with the Organization that are visible to the requesting user. An administrator can see all Organization-managed devices, while a non-administrator can see the Devices for the Networks they are a member of.</td></tr><tr><td><code>networks</code></td><td>list</td><td>A list containing the IDs of all Networks associated with the Organization that are visible to the requesting user.</td></tr></tbody></table>

{% tabs %}
{% tab title="200" %}

```json
{
  "name": "Org 1"
  "id": 1,
    "description": "Where Org 1 things live.",
    "created_on": "2023-11-07T00:00:00.000000+00:00",
    "sandbox": false,
  "members": [
      {
	"role": "admin",
	"user": "user-1"
      },
      {
         "role": "member",
  	 "user": "user-2"
      }
  ],
    "devices": [],
    "networks": []
}
```

{% endtab %}

{% tab title="403" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

#### Get a list of all Organizations

<mark style="color:green;">`GET`</mark> `/v1/orgs/`

Retrieves a list of all organizations the user account has access to. This endpoint returns a paginated list of Organization objects. The call will return an empty list if no Organizations met the provided parameters, or if the requester is not a confirmed member of any Organizations (though they should be the member of their own sandbox).

<mark style="color:blue;">**Path Parameters**</mark>

None.

<mark style="color:blue;">**Query Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>per_page</code></td><td>int</td><td>The number of items to return per page (default=50)</td></tr><tr><td><code>page</code></td><td>int</td><td>The page number to return (default=1)</td></tr><tr><td><code>sort</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>filter</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>limit</code></td><td>int, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr></tbody></table>

<mark style="color:blue;">**Response**</mark>

*Body*

Please see the [single Organization](#get-a-single-organization) section above for details on the response body.

*Meta*

<table><thead><tr><th width="217">Name</th><th width="134">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>first_url</code></td><td>string</td><td>The url of the first page in the collection</td></tr><tr><td><code>last_url</code></td><td>string</td><td>The url of the last page in the collection</td></tr><tr><td><code>next_url</code></td><td>string</td><td>The url of the next page in the collection</td></tr><tr><td><code>prev_url</code></td><td>string</td><td>The url of the previous url in the collection</td></tr><tr><td><code>page</code></td><td>int</td><td>The current page number</td></tr><tr><td><code>pages</code></td><td>int</td><td>The total number of pages available</td></tr><tr><td><code>per_page</code></td><td>int</td><td>The number of records returned per page</td></tr><tr><td><code>total</code></td><td>int</td><td>The total number of records available in the query</td></tr></tbody></table>

{% tabs %}
{% tab title="200" %}

```json
{
  "data": [
      {
	"name": "Org 1"
	"id": 1,
	"description": "Where Org 1 things live.",
	"created_on": "2023-11-07T00:00:00.000000+00:00",
	"sandbox": false,
	"members": [
		{
		  "role": "admin",
		  "user": "user-1"
		},
		{
		  "role": "member",
		  "user": "user-2"
		}
	],
	"devices": [],
	"networks": []
	}
  ],
  "meta": {
      "first_url": "https://api.quant-aq.com/device-api/v1/orgs/?page=1&per_page=50",
      "last_url": "https://api.quant-aq.com/device-api/v1/orgs/?page=1&per_page=50",
      "next_url": null,
      "page": 1,
      "pages": 1,
      "per_page": 50,
      "prev_url": null,
      "total": 1
  }
}
```

{% endtab %}

{% tab title="403" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

### Networks

This is an object representing a *Network*. You can retrieve it to see basic information about a given Network including the members and Devices.

#### Get a Network

<mark style="color:green;">`GET`</mark> `/v1/orgs/{org_id}/{network_id}`

Retrieve the information for a single Network by its Organization ID and Network ID. The user must be a confirmed member of the Network, or the endpoint will return a 403.

<mark style="color:blue;">**Path Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>org_id</code></td><td>int</td><td>The ID of the Organization</td></tr><tr><td><code>network_id</code></td><td>int</td><td>The ID of the Network</td></tr></tbody></table>

<mark style="color:blue;">**Query Parameters**</mark>

None.

<mark style="color:blue;">**Response**</mark>

*Body*

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>name</code></td><td>string</td><td>The name of the Network</td></tr><tr><td><code>id</code></td><td>string</td><td>The unique identifier for the Network</td></tr><tr><td><code>description</code></td><td>string</td><td>A short description of the Network</td></tr><tr><td><code>created_on</code></td><td>datetime</td><td>An ISO-formatted timestamp representing the creation date of the Network</td></tr><tr><td><code>members</code></td><td>list</td><td>A list containing the confirmed members of the Network that are visible to the requesting user. </td></tr><tr><td><code>devices</code></td><td>list</td><td>A list containing the serial number of all Devices associated with the Network.</td></tr></tbody></table>

{% tabs %}
{% tab title="200" %}

```json
{
    "name": "Network 1",
		"id": 1,
		"description": "Where Network 1 things live.",
    "organization": 1,
		"created_on": "2023-11-07T00:00:00.000000+00:00",
		"members": [
        {
          "role": "Operator",
          "user": "user1"
        },
				{
          "role": "Researcher",
          "user": "user2"
        },
    ],
		"devices": []
}

```

{% endtab %}

{% tab title="403" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

#### Get a list of Networks

<mark style="color:green;">`GET`</mark> `/v1/orgs/{org_id}/networks/`

Retrieves a list of all visible Networks belonging to a given Organization. This endpoint is scoped behind the Organization endpoint, so you must provide an Organization ID. An Organization’s Network is visible to a user if they are an Organization administrator or a member of the Network. The Organization must be visible to the requester, or the endpoint will return a 403.

<mark style="color:blue;">**Path Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>org_id</code></td><td>int</td><td>The ID of the Organization</td></tr></tbody></table>

<mark style="color:blue;">**Query Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>per_page</code></td><td>int</td><td>The number of items to return per page (default=50)</td></tr><tr><td><code>page</code></td><td>int</td><td>The page number to return (default=1)</td></tr><tr><td><code>sort</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>filter</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>limit</code></td><td>int, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr></tbody></table>

<mark style="color:blue;">**Response**</mark>

*Body*

Please see the [single Network](#get-a-network) section above for details on the response body.

*Meta*

<table><thead><tr><th width="217">Name</th><th width="134">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>first_url</code></td><td>string</td><td>The url of the first page in the collection</td></tr><tr><td><code>last_url</code></td><td>string</td><td>The url of the last page in the collection</td></tr><tr><td><code>next_url</code></td><td>string</td><td>The url of the next page in the collection</td></tr><tr><td><code>prev_url</code></td><td>string</td><td>The url of the previous url in the collection</td></tr><tr><td><code>page</code></td><td>int</td><td>The current page number</td></tr><tr><td><code>pages</code></td><td>int</td><td>The total number of pages available</td></tr><tr><td><code>per_page</code></td><td>int</td><td>The number of records returned per page</td></tr><tr><td><code>total</code></td><td>int</td><td>The total number of records available in the query</td></tr></tbody></table>

{% tabs %}
{% tab title="200" %}

```json
{
  "data": [
      {
			    "name": "Network 1",
					"id": 1,
					"description": "Where Network 1 things live.",
			    "organization": 1,
					"created_on": "2023-11-07T00:00:00.000000+00:00",
					"members": [
			        {
			          "role": "Operator",
			          "user": "user1"
			        },
							{
			          "role": "Researcher",
			          "user": "user2"
			        },
			    ],
					"devices": []
			}
  ],
  "meta": {
      "first_url": "https://api.quant-aq.com/device-api/v1/orgs/1/networks/?page=1&per_page=50",
      "last_url": "https://api.quant-aq.com/device-api/v1/orgs/1/networks/?page=1&per_page=50",
      "next_url": null,
      "page": 1,
      "pages": 1,
      "per_page": 50,
      "prev_url": null,
      "total": 1
  }
}
```

{% endtab %}

{% tab title="403" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

### Data

This is an object representing your data for a given Device. You can retrieve it as a list for either *raw* or *final* data

#### Get final data

<mark style="color:green;">`GET`</mark> `/v1/devices/{serial_number}/data/`

Retrieves a paginated list of data for a specific device using its serial number.

<mark style="color:blue;">**Path Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>serial_number</code></td><td>string</td><td>The serial number of the device you would like to query</td></tr></tbody></table>

<mark style="color:blue;">**Query Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>per_page</code></td><td>int</td><td>The number of items to return per page (default=50)</td></tr><tr><td><code>page</code></td><td>int</td><td>The page number to return (default=1)</td></tr><tr><td><code>sort</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>filter</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>limit</code></td><td>int, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr></tbody></table>

<mark style="color:blue;">**Response**</mark>

*Body*

Please see the product manual for the type of Device you are querying for details on the response body. These are located in the "Hardware" section of these docs.

*Meta*

<table><thead><tr><th width="217">Name</th><th width="134">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>first_url</code></td><td>string</td><td>The url of the first page in the collection</td></tr><tr><td><code>last_url</code></td><td>string</td><td>The url of the last page in the collection</td></tr><tr><td><code>next_url</code></td><td>string</td><td>The url of the next page in the collection</td></tr><tr><td><code>prev_url</code></td><td>string</td><td>The url of the previous url in the collection</td></tr><tr><td><code>page</code></td><td>int</td><td>The current page number</td></tr><tr><td><code>pages</code></td><td>int</td><td>The total number of pages available</td></tr><tr><td><code>per_page</code></td><td>int</td><td>The number of records returned per page</td></tr><tr><td><code>total</code></td><td>int</td><td>The total number of records available in the query</td></tr></tbody></table>

{% tabs %}
{% tab title="200" %}

```json
{
    "data": [
						{
	            "co": 51.106268512085,
	            "co2": 421.793483200912,
	            "geo": {
	                "lat": 40.9844188816344,
	                "lon": 105.561207967016
	            },
	            "no": 10.2810514330163,
	            "no2": 56.8233499407749,
	            "noise": 6.29058420281369,
	            "o3": 37.946070157595,
	            "pm1": 8.91967278706223,
	            "pm10": 14.2017895600789,
	            "pm25": 9.07509558015509,
	            "pressure": 101454.562990336,
	            "rh_manifold": 73.2982119788483,
	            "sn": "SN000-001",
	            "solar": 8.49282458496783,
	            "temp_box": 35.226457866451,
	            "temp_manifold": 7.28921112549997,
	            "timestamp": "2020-06-08T15:31:16.895459",
	            "timestamp_local": "2020-06-08T09:31:16.895459",
	            "tvoc": null,
	            "url": "https://api.quant-aq.com/device-api/v1/devices/SN000-001/data/19",
	            "wind_dir": 323.38596795112,
	            "wind_speed": 99.8816892936835
	        }
    ],
    "meta": {
        "first_url": "https://api.quant-aq.com/device-api/v1/devices/SN000-001/data/?page=1&per_page=50&limit=100",
        "last_url": "https://api.quant-aq.com/device-api/v1/devices/SN000-001/data/?page=2&per_page=50&limit=100",
        "next_url": "https://api.quant-aq.com/device-api/v1/devices/SN000-001/data/?page=2&per_page=50&limit=100",
        "page": 1,
        "pages": 2,
        "per_page": 50,
        "prev_url": null,
        "total": 100
    }
}
```

{% endtab %}

{% tab title="403" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

#### Get raw data

<mark style="color:green;">`GET`</mark> `/v1/devices/{serial_number}/data/raw/`

Retrieves a paginated list of raw data for a specific device using its serial number.

<mark style="color:blue;">**Path Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>serial_number</code></td><td>string</td><td>The serial number of the device you would like to query</td></tr></tbody></table>

<mark style="color:blue;">**Query Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>per_page</code></td><td>int</td><td>The number of items to return per page (default=50)</td></tr><tr><td><code>page</code></td><td>int</td><td>The page number to return (default=1)</td></tr><tr><td><code>sort</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>filter</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>limit</code></td><td>int, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr></tbody></table>

<mark style="color:blue;">**Response**</mark>

*Body*

Please see the product manual for the type of Device you are querying for details on the response body. These are located in the "Hardware" section of these docs.

*Meta*

<table><thead><tr><th width="217">Name</th><th width="134">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>first_url</code></td><td>string</td><td>The url of the first page in the collection</td></tr><tr><td><code>last_url</code></td><td>string</td><td>The url of the last page in the collection</td></tr><tr><td><code>next_url</code></td><td>string</td><td>The url of the next page in the collection</td></tr><tr><td><code>prev_url</code></td><td>string</td><td>The url of the previous url in the collection</td></tr><tr><td><code>page</code></td><td>int</td><td>The current page number</td></tr><tr><td><code>pages</code></td><td>int</td><td>The total number of pages available</td></tr><tr><td><code>per_page</code></td><td>int</td><td>The number of records returned per page</td></tr><tr><td><code>total</code></td><td>int</td><td>The total number of records available in the query</td></tr></tbody></table>

{% tabs %}
{% tab title="200" %}

```json
{
  "data": [
			{
          "bin0": 286.647741870419,
          "bin1": 551.701930611041,
          "bin10": 46.7706898657725,
          "bin11": 29.584787450594,
          "bin12": 50.7844931631582,
          "bin13": 21.5517228689086,
          "bin14": 44.4108140986913,
          "bin2": 221.637921828236,
          "bin3": 275.16465539171,
          "bin4": 312.552750081673,
          "bin5": 224.606340244391,
          "bin6": 230.723866268078,
          "bin7": 40.6604798027605,
          "bin8": 86.764139275662,
          "bin9": 76.3482566483437,
          "co2_raw": 959.118224004688,
          "co_ae": 911.5526546364,
          "co_diff": null,
          "co_we": 467.476827385698,
          "dew_point": 2.1147447373898,
          "flag": 64,
          "geo": {
              "lat": 40.9844188816344,
              "lon": 105.561207967016
          },
          "no2_ae": 579.782539043588,
          "no2_diff": null,
          "no2_we": 614.951076396963,
          "no_ae": 789.090772676965,
          "no_diff": null,
          "no_we": 439.438007376347,
          "noise": 6.29058420281369,
          "o3_ae": 455.557344482557,
          "o3_diff": null,
          "o3_we": 669.05302084695,
          "opc_flow": 0.569001807871506,
          "opc_sample_time": null,
          "pressure": 101454.562990336,
          "rh_manifold": 73.2982119788483,
          "sn": "SN000-001",
          "solar": 8.49282458496783,
          "temp_box": 35.226457866451,
          "temp_manifold": 7.28921112549997,
          "timestamp": "2020-06-08T15:31:16.895459",
          "timestamp_local": "2020-06-08T09:31:16.895459",
          "url": "https://api.quant-aq.com/device-api/v1/devices/SN000-001/data/raw/19",
          "voc_raw": 139.457791015991,
          "wind_dir": 323.38596795112,
          "wind_speed": 99.8816892936835
      }
  ],
  "meta": {
      "first_url": "https://api.quant-aq.com/device-api/v1/devices/SN000-001/data/raw/?page=1&per_page=50&limit=100",
      "last_url": "https://api.quant-aq.com/device-api/v1/devices/SN000-001/data/raw/?page=2&per_page=50&limit=100",
      "next_url": "https://api.quant-aq.com/device-api/v1/devices/SN000-001/data/raw/?page=2&per_page=50&limit=100",
      "page": 1,
      "pages": 2,
      "per_page": 50,
      "prev_url": null,
      "total": 100
  }
}
```

{% endtab %}

{% tab title="403" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

### Data by Date

{% hint style="info" %}
This section and the endpoint were added on March 31st, 2022.
{% endhint %}

This is an object representing your data for a given Device, as queried by date. You can retrieve it as a list for either *raw* or *final* data.

#### Get final data by date

<mark style="color:green;">`GET`</mark> `/v1/devices/{serial_number}/data-by-date/{date}/`

Retrieves a paginated list of final data for a specific device using its serial number for a specific date.

<mark style="color:blue;">**Path Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>serial_number</code></td><td>string</td><td>The serial number of the device you would like to query</td></tr><tr><td><code>date</code></td><td>string</td><td>The date for which you would like to return data. The format must be YYYY-MM-DD and all dates are in GMT. Thus, if you request data for 2022-01-01, it will return all data for the device on Jan. 1st GMT.</td></tr></tbody></table>

<mark style="color:blue;">**Query Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>per_page</code></td><td>int</td><td>The number of items to return per page (default=50)</td></tr><tr><td><code>page</code></td><td>int</td><td>The page number to return (default=1)</td></tr><tr><td><code>sort</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>filter</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>limit</code></td><td>int, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr></tbody></table>

<mark style="color:blue;">**Response**</mark>

*Body*

Please see the product manual for the type of Device you are querying for details on the response body. These are located in the "Hardware" section of these docs.

*Meta*

<table><thead><tr><th width="217">Name</th><th width="134">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>first_url</code></td><td>string</td><td>The url of the first page in the collection</td></tr><tr><td><code>last_url</code></td><td>string</td><td>The url of the last page in the collection</td></tr><tr><td><code>next_url</code></td><td>string</td><td>The url of the next page in the collection</td></tr><tr><td><code>prev_url</code></td><td>string</td><td>The url of the previous url in the collection</td></tr><tr><td><code>page</code></td><td>int</td><td>The current page number</td></tr><tr><td><code>pages</code></td><td>int</td><td>The total number of pages available</td></tr><tr><td><code>per_page</code></td><td>int</td><td>The number of records returned per page</td></tr><tr><td><code>total</code></td><td>int</td><td>The total number of records available in the query</td></tr></tbody></table>

{% tabs %}
{% tab title="200" %}

```json
{
    "data": [
						{
	            "co": 51.1,
	            "co2": 421.7,
	            "geo": {
	                "lat": 40.984,
	                "lon": 105.561
	            },
	            "no": 10.2810514330163,
	            "no2": 56.8233499407749,
	            "o3": 37.946070157595,
	            "pm1": 8.91967278706223,
	            "pm10": 14.2017895600789,
	            "pm25": 9.07509558015509,
	            "rh_manifold": 73.2982119788483,
	            "sn": "SN000-001",
	            "temp_box": 35.226457866451,
	            "temp_manifold": 7.28921112549997,
	            "timestamp": "2020-06-08T15:31:16.895459",
	            "timestamp_local": "2020-06-08T09:31:16.895459",
	            "url": "https://api.quant-aq.com/device-api/v1/devices/SN000-001/data/19",
	            "wind_dir": 323.38596795112,
	            "wind_speed": 99.8816892936835
	        }
    ],
    "meta": {
        "date": "2022-01-01", 
        "total": 100
    }
}
```

{% endtab %}

{% tab title="403" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

#### Get raw data by date

<mark style="color:green;">`GET`</mark> `/v1/devices/{serial_number}/data-by-date/raw/{date}/`

Retrieves a paginated list of raw data for a specific device using its serial number for a specific date.

<mark style="color:blue;">**Path Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>serial_number</code></td><td>string</td><td>The serial number of the device you would like to query</td></tr><tr><td><code>date</code></td><td>string</td><td>The date for which you would like to return data. The format must be YYYY-MM-DD and all dates are in GMT. Thus, if you request data for 2022-01-01, it will return all data for the device on Jan. 1st GMT.</td></tr></tbody></table>

<mark style="color:blue;">**Query Parameters**</mark>

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>per_page</code></td><td>int</td><td>The number of items to return per page (default=50)</td></tr><tr><td><code>page</code></td><td>int</td><td>The page number to return (default=1)</td></tr><tr><td><code>sort</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>filter</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>limit</code></td><td>int, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr></tbody></table>

<mark style="color:blue;">**Response**</mark>

*Body*

Please see the product manual for the type of Device you are querying for details on the response body. These are located in the "Hardware" section of these docs.

*Meta*

<table><thead><tr><th width="217">Name</th><th width="134">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>first_url</code></td><td>string</td><td>The url of the first page in the collection</td></tr><tr><td><code>last_url</code></td><td>string</td><td>The url of the last page in the collection</td></tr><tr><td><code>next_url</code></td><td>string</td><td>The url of the next page in the collection</td></tr><tr><td><code>prev_url</code></td><td>string</td><td>The url of the previous url in the collection</td></tr><tr><td><code>page</code></td><td>int</td><td>The current page number</td></tr><tr><td><code>pages</code></td><td>int</td><td>The total number of pages available</td></tr><tr><td><code>per_page</code></td><td>int</td><td>The number of records returned per page</td></tr><tr><td><code>total</code></td><td>int</td><td>The total number of records available in the query</td></tr></tbody></table>

{% tabs %}
{% tab title="200" %}

```json
{
  "data": [
			{
          "bin0": 286.647741870419,
          "bin1": 551.701930611041,
          "bin10": 46.7706898657725,
          "bin11": 29.584787450594,
          "bin12": 50.7844931631582,
          "bin13": 21.5517228689086,
          "bin14": 44.4108140986913,
          "bin2": 221.637921828236,
          "bin3": 275.16465539171,
          "bin4": 312.552750081673,
          "bin5": 224.606340244391,
          "bin6": 230.723866268078,
          "bin7": 40.6604798027605,
          "bin8": 86.764139275662,
          "bin9": 76.3482566483437,
          "co2_raw": 959.118224004688,
          "co_ae": 911.5526546364,
          "co_diff": null,
          "co_we": 467.476827385698,
          "dew_point": 2.1147447373898,
          "flag": 64,
          "geo": {
              "lat": 40.9844188816344,
              "lon": 105.561207967016
          },
          "no2_ae": 579.782539043588,
          "no2_diff": null,
          "no2_we": 614.951076396963,
          "no_ae": 789.090772676965,
          "no_diff": null,
          "no_we": 439.438007376347,
          "noise": 6.29058420281369,
          "o3_ae": 455.557344482557,
          "o3_diff": null,
          "o3_we": 669.05302084695,
          "opc_flow": 0.569001807871506,
          "opc_sample_time": null,
          "pressure": 101454.562990336,
          "rh_manifold": 73.2982119788483,
          "sn": "SN000-001",
          "solar": 8.49282458496783,
          "temp_box": 35.226457866451,
          "temp_manifold": 7.28921112549997,
          "timestamp": "2020-06-08T15:31:16.895459",
          "timestamp_local": "2020-06-08T09:31:16.895459",
          "url": "https://api.quant-aq.com/device-api/v1/devices/SN000-001/data/raw/19",
          "voc_raw": 139.457791015991,
          "wind_dir": 323.38596795112,
          "wind_speed": 99.8816892936835
      }
  ],
  "meta": {
      "date": "2022-01-01",
      "total": 100
  }
}
```

{% endtab %}

{% tab title="403" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

### Most Recent Data

Retrieve the most recent data record for either a single Device (by serial number), a Network (id), or an Organization (id). A list will be returned for any of them.

#### Get the most recent data

<mark style="color:green;">`GET`</mark> `/v1/data/most-recent/`

Retrieves the data for a specific Device using its serial number or a list of Devices using an Organization ID or Network ID. If multiple parameters are used, the devices from which data is fetched must meet all conditions.

<mark style="color:blue;">**Path Parameters**</mark>

None.

<mark style="color:blue;">**Query Parameters**</mark>

{% hint style="warning" %}
At least one of `sn`, `org_id`, or `network_id` must be provided otherwise a 400 error will be returned.
{% endhint %}

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>sn</code></td><td>string</td><td>The serial number of the device in question.</td></tr><tr><td><code>org_id</code></td><td>int</td><td>The ID of the Organization.</td></tr><tr><td><code>network_id</code></td><td>int</td><td>The ID of the Network.</td></tr><tr><td><code>per_page</code></td><td>int</td><td>The number of items to return per page (default=50)</td></tr><tr><td><code>page</code></td><td>int</td><td>The page number to return (default=1)</td></tr><tr><td><code>sort</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>filter</code></td><td>string, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr><tr><td><code>limit</code></td><td>int, optional</td><td>Please see the <strong>advanced queries</strong> section at the bottom of this page for more information</td></tr></tbody></table>

<mark style="color:blue;">**Response**</mark>

*Body*

Please see the product manual for the type of Device you are querying for details on the response body. These are located in the "Hardware" section of these docs.

*Meta*

<table><thead><tr><th width="217">Name</th><th width="134">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>first_url</code></td><td>string</td><td>The url of the first page in the collection</td></tr><tr><td><code>last_url</code></td><td>string</td><td>The url of the last page in the collection</td></tr><tr><td><code>next_url</code></td><td>string</td><td>The url of the next page in the collection</td></tr><tr><td><code>prev_url</code></td><td>string</td><td>The url of the previous url in the collection</td></tr><tr><td><code>page</code></td><td>int</td><td>The current page number</td></tr><tr><td><code>pages</code></td><td>int</td><td>The total number of pages available</td></tr><tr><td><code>per_page</code></td><td>int</td><td>The number of records returned per page</td></tr><tr><td><code>total</code></td><td>int</td><td>The total number of records available in the query</td></tr></tbody></table>

{% tabs %}
{% tab title="200" %}

```json
{
    "data": [
						{
	            "co": 51.106268512085,
	            "co2": 421.793483200912,
	            "geo": {
	                "lat": 40.9844188816344,
	                "lon": 105.561207967016
	            },
	            "no": 10.2810514330163,
	            "no2": 56.8233499407749,
	            "noise": 6.29058420281369,
	            "o3": 37.946070157595,
	            "pm1": 8.91967278706223,
	            "pm10": 14.2017895600789,
	            "pm25": 9.07509558015509,
	            "pressure": 101454.562990336,
	            "rh_manifold": 73.2982119788483,
	            "sn": "SN000-001",
	            "solar": 8.49282458496783,
	            "temp_box": 35.226457866451,
	            "temp_manifold": 7.28921112549997,
	            "timestamp": "2020-06-08T15:31:16.895459",
	            "timestamp_local": "2020-06-08T09:31:16.895459",
	            "tvoc": null,
	            "url": "https://api.quant-aq.com/device-api/v1/devices/SN000-001/data/19",
	            "wind_dir": 323.38596795112,
	            "wind_speed": 99.8816892936835
	        },
					...
    ]
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "Invalid request"
}
```

{% endtab %}
{% endtabs %}

### Resampled Data

{% hint style="info" %}
As of September 24th, 2024, the resampled data downloads only provide data for completed resampling periods. Future periods and the current in-progress period will be omitted. For more information about how QuantAQ resamples data, see [this article](https://support.quant-aq.com/en/articles/8838723-how-to-download-resampled-data).
{% endhint %}

The attributes for the resampled data object depend on the model of the Device and will always return the *final* data. Generally, a list is returned containing all available data for that Device, per period.

The data returned from this endpoint differs from others in several ways. Some further remarks on the structure and contents:

* Data entries may be `null`, if there are no measurements for that period, or if the number of measurements does not meet the completeness criterion. For more information refer to [this help article](https://support.quant-aq.com/en/articles/8838723-how-to-download-resampled-data).
* Periods are included even if no measurements meet the completeness criterion.
* The number of data records (of any sort) is provided in `n_datapoints`. Note that this does not indicate that every data record has a valid measurement for every listed pollutant, since components may operate independently of each other.
* Periods are computed using the device’s local timezone. Across Daylight Savings Time borders, there may be more or less time represented by a given period. Further discussion [here](https://support.quant-aq.com/en/articles/8838723-how-to-download-resampled-data).
* Times are provided in both local and UTC time, with offsets included.
* Averaging is done naively across all data within the period and is not intended to match the National Ambient Air Quality Standard (NAAQS) or other specific averaging logic and is provided for convenience only

#### Get resampled data

Retrieves the data for a specific device using its serial number.

<mark style="color:green;">`GET`</mark> `/v1/data/resampled/`

<mark style="color:blue;">**Path Parameters**</mark>

None.

<mark style="color:blue;">**Query Parameters**</mark>

{% hint style="warning" %}
&#x20;`sn`, `start_date`,  `end_date`, and `period` must be provided otherwise a 400 error will be returned.
{% endhint %}

<table><thead><tr><th width="206">Name</th><th width="156">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>sn</code></td><td>string, required</td><td>The serial number of the device in question.</td></tr><tr><td><code>start_date</code></td><td>string, required</td><td>The ID of the Organization.</td></tr><tr><td><code>end_date</code></td><td>string, required</td><td>The ID of the Network.</td></tr><tr><td><code>period</code></td><td>string, required</td><td>The length of period at which the data should be resampled. Options: 15m (15 minutes), 1h (1 hour), 8h (8 hours), 1d (1 day)</td></tr></tbody></table>

<mark style="color:blue;">**Response**</mark>

*Body*

The data available will depend on the device in question, but will be shaped roughly like the following, with one object per time period. Consult the Hardware section of the documentation for a sense of what columns your device supports.

{% tabs %}
{% tab title="200" %}

```json
{
  "data": [
    {
      "co": 139.156,
      "n_datapoints": 60,
      "no": 3.705,
      "no2": 2.367,
      "o3": 42.106,
      "period_end": "2025-05-27T01:00:00-07:00",
      "period_end_utc": "2025-05-27T08:00:00+00:00",
      "period_start": "2025-05-27T00:00:00-07:00",
      "period_start_utc": "2025-05-27T07:00:00+00:00",
      "pm1": 1.514,
      "pm10": 14.993,
      "pm25": 2.962,
      "sample_rh": 62.408,
      "sample_temp": 13.57,
      "sn": "MOD-X-00001",
      "wd": 62.148,
      "ws": 0.896,
      "ws_scalar": 1.006,
      "wx_dew_point": 6.696,
      "wx_pressure": 1019.945,
      "wx_rh": 65.304,
      "wx_temp": 12.985
    },,
    ...
    
}
```

{% endtab %}

{% tab title="400" %}

```json
{
  "error": "bad request",
  "message": "period parameter should be one of 1h|15m|8h|1d"
}
```

{% endtab %}
{% endtabs %}

### Meta Data

### Logs

## Advanced Queries

Most QuantAQ Cloud API endpoints support advanced queries that allow you to filter, limit, and sort your results. All endpoints that return paginated data - such as retrieving data points - support these requests.

### Filtering requests

To filter a query, use the `filter` keyword argument with the format `filter=<parameter>,<filter spec>,<value>`. Multiple filters can be combined using a `;` to build complex queries. For example, if we want to return the data points where PM2.5 is between 25 and 50 µg/m3, we would write `filter=pm25,ge,25;pm25,le,50;`.

A full request might then look like:

```sh
$ http -a <your-api-key-here>: GET \
        "https://api.quant-aq.com/device-api/v1/devices/<sn>/data/?filter=pm25,ge,25;pm25,le,50;"
```

\
The following filter specs are supported and available to use:

* `eq`: = (equals)
* `ne`: ≠ (not equals)
* `lt`: < (less than)
* `gt`: > (greater than)
* `ge`: ≥ (greater than or equal to)
* `le`: ≤ (less than or equal to)
* `in`: in
* `like`: like

### Limiting requests

To limit the number of data points returned for any given request, use the `limit` keyword argument with the number of data you would like returned. For example, to return just the first 5 items, use `limit=5`. If you are calling an endpoint that returns paginated data and would like to return a specific number of data per page, you can alternatively (or additionally) use the `per_page` keyword argument.

### Sorting requests

To return data in a specific order, you can use the `sort` keyword argument with format `sort=<parameter>,<order>` where `order` is one of `asc` or `desc`. For example, if you want to return the data descended by timestamp:

```sh
$ http -a <api-key>: GET \
    https://api.quant-aq.com/device-api/v1/devices/<serial number>/data/?sort=timestamp,desc

```

## Other Resources

### SDKs

#### py-quantaq

[`py-quantaq`](https://github.com/quant-aq/py-quantaq) is the official python API wrapper for the QuantAQ Cloud API and is maintained and supported by QuantAQ. Full documentation can be found [here](https://quant-aq.github.io/py-quantaq/). For questions specfiic to `py-quantaq`, please use the [GitHub repository issues page](https://github.com/quant-aq/py-quantaq/issues).

#### r-quantaq

&#x20;[`r-quantaq`](https://github.com/quant-aq/r-quantaq) is the official R API wrapper for the QuantAQ Cloud API and is maintained and supported by QuantAQ. Full documentation can be found [here](https://github.com/quant-aq/r-quantaq). For questions specfiic to `R-quantaq`, please use the [GitHub repository issues page](https://github.com/quant-aq/r-quantaq/issues).

## Changelog

<table><thead><tr><th width="190">Date</th><th>Release Notes</th></tr></thead><tbody><tr><td>September 24th, 2024</td><td><p></p><ul><li>The Resampled Data endpoint now omits future periods on the current day instead of including them as null.</li></ul></td></tr><tr><td>February 27th, 2024</td><td><p></p><ul><li>A Resampled Data endpoint was added (<code>/v1/data/resampled/</code>)</li></ul></td></tr><tr><td>December 28th, 2023</td><td><p></p><ul><li>All teams-related endpoints and parameters were removed, following deprecation in Summer 2023</li><li>After significant user feedback, “Public” devices are no longer accessible via the API to unauthorized users without Org or Network access. (Public devices remain visible through the QuantAQ Cloud web app)</li></ul></td></tr><tr><td>November 7th, 2023</td><td><p></p><ul><li><p>Several new endpoints were added, to accommodate organization and network requests:</p><ul><li><code>/v1/orgs/</code></li><li><code>/v1/orgs/&#x3C;org_id>/</code></li><li><code>/v1/orgs/&#x3C;org_id>/networks/</code></li><li><code>/v1/orgs/&#x3C;org_id>/networks/&#x3C;network_id></code></li></ul></li><li><p>Two endpoints were changed to permit filtering by organization and network:</p><ul><li><code>/v1/data/most-recent/</code> now accepts optional <code>org_id</code> and <code>network_id</code> filtering parameters</li><li><code>/v1/data/devices/</code> now accepts optional <code>org_id</code> and <code>network_id</code> filtering parameters</li></ul></li></ul></td></tr><tr><td>March 31st, 2022</td><td><p></p><ul><li>Two new endpoints were added (<code>/devices/&#x3C;sn>/data-by-date/&#x3C;date>/</code>, <code>/devices/&#x3C;sn>/data-by-date/raw/&#x3C;date>/</code>) to allow users to more efficiently query large amounts of data</li></ul></td></tr><tr><td>January 26th, 2022</td><td><p></p><ul><li>A new endpoint was added (<code>/data/most-recent/</code>) to allow users to query the most recent data for a single device or team of devices.</li></ul></td></tr><tr><td>January 11th, 2021</td><td><p></p><ul><li>the <code>devices/</code> endpoint was updated to allow for a new parameter (<code>team</code>) which permits users to query available devices by team name. Simply add <code>?team=team-1</code> and you will only be returned the available devices for the requested team. If the team name does not exist or have any devices, an empty list will be returned. If you would like to return all available devices across all of your teams, simply omit the team parameter as before.</li></ul></td></tr></tbody></table>


# Command Line Interface

The QuantAQ Command Line Interface (CLI) tool provides easy-to-use tools to munge data associated with QuantAQ's air quality sensor data.

Check it out on GitHub!

{% embed url="<https://github.com/quant-aq/cli>" %}

## Overview

The purpose of the CLI tool is to make data munging a breeze! There are currently built-in functionality to allow you to easily:

* concatenate files
* merge files
* flag data
* expunge data
* resample data

For more information on usage, check out the complete docs.

### Installation

To install the most recent release:

```
$ pip install -U quantaq-cli
```

### Examples

For examples and usage, please check out the full documentation page [here](https://quant-aq.github.io/cli/index.html).


