{"id":46801,"date":"2025-01-08T00:00:00","date_gmt":"2025-01-08T08:00:00","guid":{"rendered":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/blog\/griddb-air-quality-california-pi-cloud\/"},"modified":"2025-11-13T12:57:00","modified_gmt":"2025-11-13T20:57:00","slug":"griddb-air-quality-california-pi-cloud","status":"publish","type":"post","link":"https:\/\/www.griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/","title":{"rendered":"Monitoring Air Quality in California using Home Assistant, Raspberry Pi, and GridDB Cloud"},"content":{"rendered":"<p>Despite humanity&#8217;s (lackluster) efforts, climate change has become an omnipresent, undeniable force. Though there are many side effects that come with a rising global average temperature, today I want to focus on wildfires and their affect on the air quality of all surrounding areas; when a 100-acre-fire is burning up a Californian forest, all of that debris and particle matter get kicked up into the atmosphere, becoming potentially dangerous, inhalable matter.<\/p>\n<p>Of course, there are various <em>other<\/em> factors which can (and do) contribute to the quality of the air we breathe. To me, this means that even if there isn&#8217;t a wildfire nearby causing spikes in AQI (Air Quality Index), there is still a reason to be informed and aware of what the air quality is like at any given moment.<\/p>\n<h2>The Project<\/h2>\n<p>For this article, we were interested in measuring the air quality inside of our homes. Specifically, we wanted to take live readings of our air quality data, save it into persistent storage, and then notify the inhabitants when the air quality grew passed a certain threshold.<\/p>\n<p>To accomplish our goal, we sought to integrate GridDB Cloud with the open source smart home solution known as <a href=\"https:\/\/www.home-assistant.io\/\">Home Assistant<\/a>. If you are unfamiliar, Home Assistant is an &#8220;Internet of things (IoT) ecosystem-independent integration platform and central control system for smart home devices, with a focus on local control&#8221;. Typically, end users install the software onto their home servers to control aspects of their internet-connected physical devices. As an example, one might install Home Assistant to act as their smart hub to control their smart light bulbs, smart robovac, etc.<\/p>\n<p>The beauty of Home Assistant is in its versatility and flexibility. For instance, because it&#8217;s completely open source and built for tinkerers\/developers, users can roll their own solutions for their own specific use cases, and build their own automations. For our case, we were interested in being able to save all of the raw, unfiltered sensor data into GridDB Cloud at a resolution of 1 reading\/second, and then using the Home Assistant to query the values needed to do what we want, eventually being able to notify those who live in the same space as the sensor that the air quality is approaching dangerous levels in some tangible way.<\/p>\n<h3>Project Specifics and the PM1 Particle<\/h3>\n<p>The idea goes like this, we use a single board computer to connect to a sensor which will capture raw air quality data. We then send that raw data into GridDB cloud at a resolution of 1 particle\/second. Our Home Assistant can then query the data and downsample whatever information is necessary to accomplish our goal.<\/p>\n<p>To begin, we have connected an air quality sensor &#8212; <a href=\"https:\/\/www.adafruit.com\/product\/4632\">Adafruit PMSA003I Air Quality Breakout<\/a> &#8212; to a raspberry pi. We then use a python script to read and send the sensor readings up to GridDB Cloud every 1 second via HTTP Request. With our data being saved into persistent storage with GridDB Cloud, we can make HTTP Requests to query our dataset with <code>SQL Select statements<\/code>. In this case, we want to use Home Assistant to query our dataset to alert us of higher than normal particle matters in the air at our locations. We also want to include an easy to read sensor reading right on our Home Assistant dashboard with rolling averages.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/05\/Diagram.jpg\"><img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/05\/Diagram.jpg\" alt=\"\" width=\"1280\" height=\"720\" class=\"aligncenter size-full wp-image-30111\" srcset=\"\/wp-content\/uploads\/2024\/05\/Diagram.jpg 1280w, \/wp-content\/uploads\/2024\/05\/Diagram-300x169.jpg 300w, \/wp-content\/uploads\/2024\/05\/Diagram-768x432.jpg 768w, \/wp-content\/uploads\/2024\/05\/Diagram-1024x576.jpg 1024w, \/wp-content\/uploads\/2024\/05\/Diagram-150x85.jpg 150w, \/wp-content\/uploads\/2024\/05\/Diagram-600x338.jpg 600w\" sizes=\"(max-width: 1280px) 100vw, 1280px\" \/><\/a><\/p>\n<p>As a sidenote: an interesting point about this particular sensor is that it can read matter as small as 1 micron (labeled as <code>PM1<\/code>). These particles are so small that they can <a href=\"https:\/\/www.iqair.com\/us\/newsroom\/pm1\">penetrate lung tissue and get directly into your bloodstream<\/a>; and because this particle is so tiny, it&#8217;s only detectable by specialized equipment, including the sensor linked above. Because of the lack of readily available sources of PM1 readings, this particle will be the focus of our queries for notifying the home inhabitants of its increasing levels.<\/p>\n<h2>Project Requirements<\/h2>\n<p>If you would like to follow along, you will need the following:<\/p>\n<ol>\n<li>Free GridDB Cloud Account a. You can read instructions on how to sign up for a free GridDB cloud account from here: <a href=\"https:\/\/form.ict-toshiba.jp\/download_form_griddb_cloud_freeplan_e?utm_source=griddbnet&amp;utm_medium=home-assistant-blog\">GridDB Free Plan<\/a>. Accompanying blog: <a href=\"https:\/\/griddb.net\/en\/blog\/griddb-cloud-quick-start-guide\/\">GridDB Cloud Quick Start<\/a><\/li>\n<li>Air Quality sensor <\/li>\n<li>Means of connecting the sensor to a computer (single board or otherwise)<\/li>\n<\/ol>\n<p>Once you have set up the necessary hardware and can connect to your GridDB Cloud database, you can grab the source code from here: <a href=\"https:\/\/github.com\/griddbnet\/Blogs\/tree\/air_quality_sensor\">GitHub<\/a> to run the simple python script to send sensor readings.<\/p>\n<h2>Connecting the Hardware<\/h2>\n<p>In my case, I bought the air quality sensor attached with a STEMMA Connector; to connect it to the Raspberry Pi 4, I bought a <a href=\"https:\/\/www.adafruit.com\/product\/4688\">STEMMA Hat<\/a> and a STEMMA wire. If you do not want to purchase a STEMMA hat, you can also solder the pins onto the sensor and use a breadboard to connect to the Raspberry Pi&#8217;s GPIO pins. If you go this route, you may need to alter the python script provided by our source code &#8212; you can read more about how to physically connect this air quality sensor through their documentation page: <a href=\"https:\/\/learn.adafruit.com\/pmsa003i?view=all\">Docs<\/a>.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/05\/hardware-scaled.jpg\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/05\/hardware-scaled.jpg\" alt=\"\" width=\"1739\" height=\"2560\" class=\"aligncenter size-full wp-image-30112\" srcset=\"\/wp-content\/uploads\/2024\/05\/hardware-scaled.jpg 1739w, \/wp-content\/uploads\/2024\/05\/hardware-204x300.jpg 204w, \/wp-content\/uploads\/2024\/05\/hardware-696x1024.jpg 696w, \/wp-content\/uploads\/2024\/05\/hardware-768x1131.jpg 768w, \/wp-content\/uploads\/2024\/05\/hardware-1043x1536.jpg 1043w, \/wp-content\/uploads\/2024\/05\/hardware-1391x2048.jpg 1391w, \/wp-content\/uploads\/2024\/05\/hardware-600x883.jpg 600w\" sizes=\"(max-width: 1739px) 100vw, 1739px\" \/><\/a><\/p>\n<h2>Software<\/h2>\n<p>Now let&#8217;s focus on the software that makes this project go.<\/p>\n<h3>Python Script for Container Creation and Pushing Data<\/h3>\n<p>First and foremost, let&#8217;s discuss the script which sends the sensor readings as HTTP requests. It is a modified version of the example script provided directly by ada fruit&#8217;s documentation. The data structure of the incoming data readings are already laid out in convenient dictionary matter, so we simply need to iterate through and make the values match up with how we lay out our schema on container creation. So first, here&#8217;s the script for container creation:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\">import http.client\nimport json\n\nconn = http.client.HTTPSConnection(\"cloud5197.griddb.com\")\npayload = json.dumps({\n  \"container_name\": \"aqdata\",\n  \"container_type\": \"TIME_SERIES\",\n  \"rowkey\": True,\n  \"columns\": [\n    {\n      \"name\": \"ts\",\n      \"type\": \"TIMESTAMP\"\n    },\n    {\n      \"name\": \"pm1\",\n      \"type\": \"DOUBLE\"\n    },\n    {\n      \"name\": \"pm25\",\n      \"type\": \"DOUBLE\"\n    },\n    {\n      \"name\": \"pm10\",\n      \"type\": \"DOUBLE\"\n    },\n    {\n      \"name\": \"pm1e\",\n      \"type\": \"DOUBLE\"\n    },\n    {\n      \"name\": \"pm25e\",\n      \"type\": \"DOUBLE\"\n    },\n    {\n      \"name\": \"pm10e\",\n      \"type\": \"DOUBLE\"\n    },\n    {\n      \"name\": \"particles03\",\n      \"type\": \"DOUBLE\"\n    },\n    {\n      \"name\": \"particles05\",\n      \"type\": \"DOUBLE\"\n    },\n    {\n      \"name\": \"particles10\",\n      \"type\": \"DOUBLE\"\n    },\n    {\n      \"name\": \"particles25\",\n      \"type\": \"DOUBLE\"\n    },\n    {\n      \"name\": \"particles50\",\n      \"type\": \"DOUBLE\"\n    },\n    {\n      \"name\": \"particles100\",\n      \"type\": \"DOUBLE\"\n    }\n  ]\n})\nheaders = {\n  'Content-Type': 'application\/json',\n  'Authorization': 'Basic &lt;redacted>'\n}\nconn.request(\"POST\", \"\/griddb\/v2\/gs_clustermfcloud5197\/dbs\/B2xcGQJy\/containers\", payload, headers)\nres = conn.getresponse()\ndata = res.read()\nprint(data.decode(\"utf-8\"))&lt;\/redacted><\/code><\/pre>\n<\/div>\n<p>For the schema, we simply just used a 1:1 mapping to the <code>aqdata<\/code> dictionary returned by our sensor readings. Even if we don&#8217;t intend to use all of these data points, the data readouts are so small, we keep them in.<\/p>\n<p>Next, let&#8217;s take a look at the script that will push sensor readings to our GridDB Cloud instance. It will read the sensor data every 1 second, and then make an HTTP Request every second to push that data into the Cloud.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-python\"># SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries\n# SPDX-License-Identifier: MIT\n\n\"\"\"\nExample sketch to connect to PM2.5 sensor with either I2C or UART.\n\"\"\"\n\n# pylint: disable=unused-import\nimport time\nimport datetime\nimport board\nimport busio\nfrom digitalio import DigitalInOut, Direction, Pull\nfrom adafruit_pm25.i2c import PM25_I2C\n\n\nimport http.client\nimport json\n\nconn = http.client.HTTPSConnection(\"cloud5197.griddb.com\")\nheaders = {\n  'Content-Type': 'application\/json',\n  'Authorization': 'Basic &lt;redacted>'\n}\n\nreset_pin = None\ni2c = busio.I2C(board.SCL, board.SDA, frequency=100000)\n# Connect to a PM2.5 sensor over I2C\npm25 = PM25_I2C(i2c, reset_pin)\n\nprint(\"Found PM2.5 sensor, reading data...\")\n\nwhile True:\n    time.sleep(1)\n\n    try:\n        aqdata = pm25.read()\n        # print(aqdata)\n        current_time = datetime.datetime.utcnow().replace(microsecond=0)\n        now = current_time.strftime('%Y-%m-%dT%H:%M:%S.%fZ')\n       # print(now)\n        temp = []\n        temp.append(now)\n    except RuntimeError:\n        print(\"Unable to read from sensor, retrying...\")\n        continue\n    \n    for data in aqdata.values():\n        temp.append(data)\n    payload = json.dumps([temp])\n    print(payload)\n    conn.request(\"PUT\", \"\/griddb\/v2\/gs_clustermfcloud5197\/dbs\/B2xcGQJy\/containers\/aqdata\/rows\", payload, headers)\n    res = conn.getresponse()\n    data = res.read()\n    print(data.decode(\"utf-8\"))&lt;\/redacted><\/code><\/pre>\n<\/div>\n<p>As explained above, there is nothing fancy or extraordinary about this script; it simply reads sensor data and then immediately pushes it out to the Cloud with a timestamp attached. The one thing to note, though, is that the GridDB Cloud is by default in UTC Time, so I have altered the timestamps to be attached to the data results to match UTC for consistency&#8217;s sake.<\/p>\n<p>And now that we have our data available in the cloud, we can move on to integrating it with other technologies.<\/p>\n<h3>Home Assistant<\/h3>\n<p>Home automation software comes in many varieties, with many companies providing their own hubs sold alongside their own products. Home assistant is unique in that it is, 1. completely open source, and 2. made to integrate with all manner of physical and virtual devices. For example, in my own personal home environment, I have Home Assistant running on a Raspberry Pi. To allow it to communicate with other physical devices, I have installed a Zigbee\/Z-Wave USB Stick. If you are unfamiliar, Zigbee and Z-Wave are protocols used by smart home devices to communicate with their hubs. In my case, most of my smart light bulbs communicate through Zigbee, for example.<\/p>\n<p>In any case, through Home Assistant, we can create various scripts\/automations for getting things done. Some examples can be: turn on bedroom lights at 1% at wake up time, or play my Spotify playlist every day at lunch time, etc etc. In the case of our air quality sensor, we can send out a direct HTTP Query against our sensor data and do <code>something<\/code> if our readings are higher than a certain threshold. For this blog, I have set up my home to turn my living room light bulbs <code>on<\/code> and to <code>red<\/code> if the <code>pm1<\/code> particles are above a certain threshold, over the past 1 hour. But of course, because Home Assistant is flexible, you could set up any sort of notification method you&#8217;d like, including emails, phone push notifications, or even turning on your robovac!<\/p>\n<p>So, to continue on, we will need to first formulate our query on sensor readings, learn how to make HTTP Requests through Home Assistant, and learn how to act on the data returned by our query. After we set up our notifcation system for high sensor reading averages, we will also want to display all sensor readings in our Home Assistant dashboard.<\/p>\n<h4>Formulating our Query<\/h4>\n<p>First, let&#8217;s get our query settled. From my cursory research, <code>pm1<\/code> particles are potentially the most threatening to our health because those particles are <em>so<\/em> tiny they can be inhaled and absorbed directly through the lungs; we will want to set up an alert for these particles.<\/p>\n<p>Before we begin, Let&#8217;s use <code>cURL<\/code> or Postman to test our HTTP Queries until we get what we are looking for; in my case, I used postman until I was happy with the results. The query I settled is the following: <code>SELECT AVG(pm1) FROM aqdata WHERE ts &gt; TIMESTAMP_ADD(HOUR, NOW(), -1) AND ts &lt; NOW() AND pm1 &gt; 10 \"<\/code>. This query will look at the data from the past 1 hour and will return with data if the avg value is over 10. Though please note I did not do strict research on what consitutes an unhealthy amount of <code>pm1<\/code> particles, this is simply for demo purposes. But now that we have our query, we can figure out how to make <code>HTTP REQUESTS<\/code> through Home Assistant.<\/p>\n<h4>Making HTTP Requests with Home Assistant<\/h4>\n<p>Within the <code>\/config<\/code> directory of the Home Assistant, there are a bunch of <code>yaml<\/code> files which are used to make configuration and automation changes to the software itself &#8212; very flexible and customizable. In our case, we want to add what is called a <code>rest_command<\/code> inside of the configuration yaml. We also would like to add an automation of what action to take based on the returned data from our <code>rest_command<\/code> &#8212; this will happen in the <code>scripts.yaml<\/code> file. Please note that all <code>yaml<\/code> files are included in the source code in the GitHub page linked above.<\/p>\n<p>So, here is what our <code>configuration.yaml<\/code> file will need to make the HTTP Request:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-bash\">#configuration.yaml\nrest_command:\n  griddb_cloud_get_aqdata:\n    url: https:\/\/cloud5197.griddb.com\/griddb\/v2\/gs_clustermfcloud5197\/dbs\/B2xcGQJy\/sql\n    method: post\n    content_type: \"application\/json\"\n    headers:\n      authorization: \"Basic &lt;redacted>\"\n    payload: '[{\"type\" : \"sql-select\", \"stmt\" : \"SELECT AVG(pm1) FROM aqdata WHERE ts > TIMESTAMP_ADD(HOUR, NOW(), -1) AND ts &lt; NOW() AND pm1 > 10 \"}]'&lt;\/redacted><\/code><\/pre>\n<\/div>\n<p>You can see here we included all neccesary things to make an HTTP Sql Select request to our Cloud instance. Here, we are naming our <code>rest_command<\/code> as <code>griddb_cloud_get_aqdata<\/code>, so now in our <code>scripts<\/code> file we can directly call upon this <code>service<\/code><\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-bash\">#scripts.yaml\nget_griddb_data:\n  sequence:\n    - service: rest_command.griddb_cloud_get_aqdata\n      response_variable: aqdata\n    - if: \"{{ aqdata['status'] == 200 }}\"\n      then:\n        - alias: Parse data\n          variables:\n            results: \"{ {aqdata['content']['results'] }}\"\n        - if: \"{{ results != 'null'}}\"\n          then:\n            service: light.turn_on\n            target:\n              entity_id: light.living_room\n            data:\n              rgb_color:\n                - 240\n                - 0\n                - 0<\/code><\/pre>\n<\/div>\n<p>As you can see, we are calling <code>rest_command.griddb_cloud_get_aqdata<\/code> as a service. This will run the HTTP Request and then parse the resulting data. If the results are null (meaning no data over our threshold), nothing will happen, but if we do get some data, we can take some action &#8212; or in this case, change the living room lights to <code>on<\/code> and change the RGB to completely red, this way everybody in the home knows that the air quality is compromised in some way.<\/p>\n<p>So to explain a bit more about how the yaml files work, the configuration yaml allows you to create <code>services<\/code>, in our case, the HTTP Request. The scripts file is for actions which may be run many times in many different spots, a bit analoguous to functions in software. And lastly we will use <code>automations.yaml<\/code> which sets up the trigger to when our script should be running. In our case, we want it run every 10 minutes &#8212; that is, every 10 minutes our Home Assistant will look at the average <code>pm1<\/code> levels over the past 1 hour and take action if it is too high.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-bash\">#automations.yaml\n- id: '1713475588605'\n  alias: Get GridDB Data\n  description: get the griddb data\n  trigger:\n  - platform: time_pattern\n    minutes: \/10\n  condition: []\n  action:\n  - service: script.get_griddb_data\n  mode: single<\/code><\/pre>\n<\/div>\n<p>You can see here that the automation is calling upon our script to get the GridDB data. You can also see that our trigger is every 10 minutes.<\/p>\n<h4>Displaying Sensor Data Onto our Home Assistant Dashboard<\/h4>\n<p>The last thing we would like to accomplish is to show our sensor readings directly onto the Home Assistant Dashboard. This will allow for all home users to constantly be aware othe readings. To do this, we will need to use the <code>sensors.yaml<\/code> file and establish new virtual &#8220;sensors&#8221; of HTTP Requests reading the sensor avg sensor data. For this, we needed to formulate a new SQL Query and this time around, I think we could make do with average readings for the past 24 hours. That query looks like this: <code>SELECT ROUND(AVG(pm1)),ROUND(AVG(pm25)),ROUND(AVG(pm10)),ROUND(AVG(particles03)),ROUND(AVG(particles05)),ROUND(AVG(particles10)),ROUND(AVG(particles25)),ROUND(AVG(particles50)),ROUND(AVG(particles100)) FROM aqdata WHERE ts &gt; TIMESTAMP_ADD(DAY, NOW(), -1) AND ts &lt; NOW()<\/code>. We simply grab all rounded averages from the past 1 day and use that info to be displayed in the dashboard.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-bash\">#sensors.yaml\n- platform: rest\n  resource: https:\/\/cloud5197.griddb.com\/griddb\/v2\/gs_clustermfcloud5197\/dbs\/B2xcGQJy\/sql\n  method: POST\n  headers:\n    authorization: \"Basic &lt;redacted>\"\n    Content-Type: application\/json\n  payload: '[{\"type\" : \"sql-select\", \"stmt\" : \"SELECT ROUND(AVG(pm1)),ROUND(AVG(pm25)),ROUND(AVG(pm10)),ROUND(AVG(particles03)),ROUND(AVG(particles05)),ROUND(AVG(particles10)),ROUND(AVG(particles25)),ROUND(AVG(particles50)),ROUND(AVG(particles100)) FROM aqdata WHERE ts > TIMESTAMP_ADD(DAY, NOW(), -1) AND ts &lt; NOW() \"}]'\n  value_template: \"{{ value_json[0].results[0][0] }}\"\n  name: \"Particle Matter 1\"\n  scan_interval: 3600&lt;\/redacted><\/code><\/pre>\n<\/div>\n<p>Here we use the <code>value_template<\/code> as the result that will be shown when we select this sensor as an entity. Unfortunately, I could not figure out how to use one singular HTTP Request with multiple values, so I needed to make each value as its own unique HTTP Request, just with a different index array position for the results. The example shown above, for instance, is for <code>pm1<\/code> as it is index 0 of our result array due to the container schema.<\/p>\n<p>So now that we have our sensor set up, we can go to the dashboard and add it to be displayed. We can click edit (the pencil in the top right corner), then add card, then glance card, and then manually add all of your sensors. For me, the text editor looks like this:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-bash\">show_name: true\nshow_icon: true\nshow_state: true\ntype: glance\nentities:\n  - entity: sensor.particle_matter_1\n  - entity: sensor.particle_matter_2_5\n  - entity: sensor.particle_matter_10\n  - entity: sensor.particles_03\n  - entity: sensor.particles_05\n  - entity: sensor.particles_10\n  - entity: sensor.particles_25\n  - entity: sensor.particles_50\n  - entity: sensor.particles_100\ntitle: Daily Air Quality Averages\ncolumns: 3\nstate_color: false<\/code><\/pre>\n<\/div>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/05\/home-assistant-dashboard.png\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2024\/05\/home-assistant-dashboard.png\" alt=\"\" width=\"480\" height=\"395\" class=\"aligncenter size-full wp-image-30113\" srcset=\"\/wp-content\/uploads\/2024\/05\/home-assistant-dashboard.png 480w, \/wp-content\/uploads\/2024\/05\/home-assistant-dashboard-300x247.png 300w\" sizes=\"(max-width: 480px) 100vw, 480px\" \/><\/a><\/p>\n<p>And now we can have our daily averages at a glance. Of course, this just a few of things you can do with this information being so readily available; this really is the beauty of having the open source Home Assistant powering your home automations, and why it&#8217;s great to have GridDB Cloud hosting all of your data &#8212; it can be accessible from anywhere and you can upload data from anywhere, as long as you have an internet connection. You could, of course, monitor poor air in remote locations, or in locations of loved ones far away and take actions however you see fit.<\/p>\n<h2>Conclusion<\/h2>\n<p>In this article, we have learned how to connect physical hardware sensor data and how to push all of that wonderful data onto GridDB Cloud. And then we learned that we can take action directly upon that data with Home Assistant.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Despite humanity&#8217;s (lackluster) efforts, climate change has become an omnipresent, undeniable force. Though there are many side effects that come with a rising global average temperature, today I want to focus on wildfires and their affect on the air quality of all surrounding areas; when a 100-acre-fire is burning up a Californian forest, all of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":30110,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-46801","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Monitoring Air Quality in California using Home Assistant, Raspberry Pi, and GridDB Cloud | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"Despite humanity&#039;s (lackluster) efforts, climate change has become an omnipresent, undeniable force. Though there are many side effects that come with a\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Monitoring Air Quality in California using Home Assistant, Raspberry Pi, and GridDB Cloud | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"Despite humanity&#039;s (lackluster) efforts, climate change has become an omnipresent, undeniable force. Though there are many side effects that come with a\" \/>\n<meta property=\"og:url\" content=\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/\" \/>\n<meta property=\"og:site_name\" content=\"GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/griddbcommunity\/\" \/>\n<meta property=\"article:published_time\" content=\"2025-01-08T08:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-13T20:57:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.griddb.net\/wp-content\/uploads\/2024\/05\/air-scaled.jpeg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1307\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Israel\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:site\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Israel\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"15 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/\"},\"author\":{\"name\":\"Israel\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/c8a430e7156a9e10af73b1fbb46c2740\"},\"headline\":\"Monitoring Air Quality in California using Home Assistant, Raspberry Pi, and GridDB Cloud\",\"datePublished\":\"2025-01-08T08:00:00+00:00\",\"dateModified\":\"2025-11-13T20:57:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/\"},\"wordCount\":2338,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2024\/05\/air-scaled.jpeg\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/\",\"url\":\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/\",\"name\":\"Monitoring Air Quality in California using Home Assistant, Raspberry Pi, and GridDB Cloud | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2024\/05\/air-scaled.jpeg\",\"datePublished\":\"2025-01-08T08:00:00+00:00\",\"dateModified\":\"2025-11-13T20:57:00+00:00\",\"description\":\"Despite humanity's (lackluster) efforts, climate change has become an omnipresent, undeniable force. Though there are many side effects that come with a\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/#primaryimage\",\"url\":\"\/wp-content\/uploads\/2024\/05\/air-scaled.jpeg\",\"contentUrl\":\"\/wp-content\/uploads\/2024\/05\/air-scaled.jpeg\",\"width\":2560,\"height\":1307},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website\",\"url\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/\",\"name\":\"GridDB: Open Source Time Series Database for IoT\",\"description\":\"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL\",\"publisher\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization\",\"name\":\"Fixstars\",\"url\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"contentUrl\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"width\":200,\"height\":83,\"caption\":\"Fixstars\"},\"image\":{\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/griddbcommunity\/\",\"https:\/\/x.com\/GridDBCommunity\",\"https:\/\/www.linkedin.com\/company\/griddb-by-toshiba\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/c8a430e7156a9e10af73b1fbb46c2740\",\"name\":\"Israel\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g\",\"caption\":\"Israel\"},\"url\":\"https:\/\/www.griddb.net\/en\/author\/israel\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Monitoring Air Quality in California using Home Assistant, Raspberry Pi, and GridDB Cloud | GridDB: Open Source Time Series Database for IoT","description":"Despite humanity's (lackluster) efforts, climate change has become an omnipresent, undeniable force. Though there are many side effects that come with a","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/","og_locale":"en_US","og_type":"article","og_title":"Monitoring Air Quality in California using Home Assistant, Raspberry Pi, and GridDB Cloud | GridDB: Open Source Time Series Database for IoT","og_description":"Despite humanity's (lackluster) efforts, climate change has become an omnipresent, undeniable force. Though there are many side effects that come with a","og_url":"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2025-01-08T08:00:00+00:00","article_modified_time":"2025-11-13T20:57:00+00:00","og_image":[{"width":2560,"height":1307,"url":"https:\/\/www.griddb.net\/wp-content\/uploads\/2024\/05\/air-scaled.jpeg","type":"image\/jpeg"}],"author":"Israel","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"Israel","Est. reading time":"15 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/#article","isPartOf":{"@id":"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/"},"author":{"name":"Israel","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/c8a430e7156a9e10af73b1fbb46c2740"},"headline":"Monitoring Air Quality in California using Home Assistant, Raspberry Pi, and GridDB Cloud","datePublished":"2025-01-08T08:00:00+00:00","dateModified":"2025-11-13T20:57:00+00:00","mainEntityOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/"},"wordCount":2338,"commentCount":0,"publisher":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2024\/05\/air-scaled.jpeg","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/","url":"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/","name":"Monitoring Air Quality in California using Home Assistant, Raspberry Pi, and GridDB Cloud | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/#primaryimage"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2024\/05\/air-scaled.jpeg","datePublished":"2025-01-08T08:00:00+00:00","dateModified":"2025-11-13T20:57:00+00:00","description":"Despite humanity's (lackluster) efforts, climate change has become an omnipresent, undeniable force. Though there are many side effects that come with a","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/blog\/griddb-air-quality-california-pi-cloud\/#primaryimage","url":"\/wp-content\/uploads\/2024\/05\/air-scaled.jpeg","contentUrl":"\/wp-content\/uploads\/2024\/05\/air-scaled.jpeg","width":2560,"height":1307},{"@type":"WebSite","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#website","url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/","name":"GridDB: Open Source Time Series Database for IoT","description":"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL","publisher":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#organization","name":"Fixstars","url":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/","url":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","contentUrl":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","width":200,"height":83,"caption":"Fixstars"},"image":{"@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/griddbcommunity\/","https:\/\/x.com\/GridDBCommunity","https:\/\/www.linkedin.com\/company\/griddb-by-toshiba"]},{"@type":"Person","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/c8a430e7156a9e10af73b1fbb46c2740","name":"Israel","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/4df8cfc155402a2928d11f80b0220037b8bd26c4f1b19c4598d826e0306e6307?s=96&d=mm&r=g","caption":"Israel"},"url":"https:\/\/www.griddb.net\/en\/author\/israel\/"}]}},"_links":{"self":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46801","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/comments?post=46801"}],"version-history":[{"count":1,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46801\/revisions"}],"predecessor-version":[{"id":51463,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46801\/revisions\/51463"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media\/30110"}],"wp:attachment":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media?parent=46801"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/categories?post=46801"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/tags?post=46801"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}