<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Sander Pettersen]]></title><description><![CDATA[Sander Pettersen]]></description><link>https://blog.thepettersen.com</link><generator>RSS for Node</generator><lastBuildDate>Tue, 28 Apr 2026 08:38:15 GMT</lastBuildDate><atom:link href="https://blog.thepettersen.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Ecowitt API]]></title><description><![CDATA[Intro
This article will cover how to download data from your weather station using ecowitt API and Python. We will set up a docker environment and store data at MongoDB.
Last year I both a ProTech 7-in-1 Station with GW1100 to monitor weather conditi...]]></description><link>https://blog.thepettersen.com/ecowitt-api</link><guid isPermaLink="true">https://blog.thepettersen.com/ecowitt-api</guid><category><![CDATA[Python 3]]></category><category><![CDATA[MongoDB]]></category><category><![CDATA[ecowitt]]></category><dc:creator><![CDATA[Sander Pettersen]]></dc:creator><pubDate>Tue, 24 Jan 2023 21:28:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/FME5mivX2ts/upload/747699c03742b8c2ac37615c7dac7e55.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-intro">Intro</h3>
<p>This article will cover how to download data from your weather station using ecowitt API and Python. We will set up a docker environment and store data at MongoDB.</p>
<p>Last year I both a ProTech 7-in-1 Station with GW1100 to monitor weather conditions at my cabin. And for this project, I want to create a weather app so my father and grandpa can check on statics and real-time data. First of all, I didn't want to call the API each time I need data and second of all, Ecowitt doesn´t store data forever.</p>
<ul>
<li><p>Data storage service on Ecowitt server: <a target="_blank" href="https://www.ecowitt.net">https://www.ecowitt.net</a></p>
<ul>
<li><p>Stores data for past 3 months at 5-minute intervals</p>
</li>
<li><p>Stores data for past 1 year at 30-minute intervals</p>
</li>
<li><p>Stores data for past 2 year at 4-hours intervals</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-lets-start-coding">Let's start coding</h3>
<p>To start you need API_KEY, APP_KEY and IEMI/MAC address for your device from <a target="_blank" href="https://ecowitt.net">ecowitt</a>. And a docker environment for deployment.</p>
<p>First of all, I recommend storing your environment variables in a .env file for good practice. And then we can import them into Python</p>
<pre><code class="lang-python"><span class="hljs-comment">#.env</span>
MONGO_HOST = mongodb://mongodb:<span class="hljs-number">27017</span>/
MONGO_USERNAME = your_username
MONGO_PASSWORD = your_password

ECOWITT_APPLICATION_KEY = some_application_key
ECOWITT_API_KEY = some_api_key
ECOWITT_IMEI_MAC = some_imei_mac
</code></pre>
<p>In this project, I have chosen to use a document database such as MongoDB for the storage of objects. But they will be used later.</p>
<pre><code class="lang-python"><span class="hljs-comment"># handler.py</span>
<span class="hljs-keyword">from</span> decouple <span class="hljs-keyword">import</span> config

ECOWITT_APPLICATION_KEY = config(<span class="hljs-string">"ECOWITT_APPLICATION_KEY"</span>)
ECOWITT_API_KEY = config(<span class="hljs-string">"ECOWITT_API_KEY"</span>)
ECOWITT_IMEI_MAC = config(<span class="hljs-string">"ECOWITT_IMEI_MAC"</span>)
MONGO_USERNAME = urllib.parse.quote_plus(config(<span class="hljs-string">"MONGO_USERNAME"</span>))
MONGO_PASSWORD = urllib.parse.quote_plus(config(<span class="hljs-string">"MONGO_PASSWORD"</span>))
</code></pre>
<p>Now that we have imported our environment keys we will set up logging for our application if something went wrong we can read it through our log file.</p>
<pre><code class="lang-python"><span class="hljs-comment"># handler.py</span>
<span class="hljs-keyword">import</span> logging

logging.basicConfig(
    filename=<span class="hljs-string">"handler.log"</span>, 
    filemode=<span class="hljs-string">"a"</span>, 
    format=<span class="hljs-string">"%(asctime)s - %(levelname)s - %(message)s"</span>, 
    datefmt=<span class="hljs-string">"%d-%b-%y %H:%M:%S"</span>,
)
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
</code></pre>
<p>In this config, we will store our logs in a file "handler.log" where all our info will be stored. In a format of time - info level - and the message. In this application, we don't have any specific logging other than if data was inserted or something went wrong from the ecowitt API</p>
<p>Next up is the function that we will use to run every time we want updates. We will first connect to our database. Then create the request to ecowitt, and then store it in the database.</p>
<pre><code class="lang-python"><span class="hljs-comment"># handler.py</span>
<span class="hljs-keyword">import</span> pymongo
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> datetime

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run_handler</span>():</span>
    <span class="hljs-comment"># </span>
    client = pymongo.MongoClient(
    <span class="hljs-comment"># protocol://username:password@(ip/docker_container)</span>
    <span class="hljs-string">'mongodb://%s:$s@mongodb'</span> % (MONGO_USERNAME, MONGO_PASSWORD)
    )
    <span class="hljs-comment"># Our database name</span>
    db = client[<span class="hljs-string">"ecowitt"</span>]

    <span class="hljs-comment"># Ecowitt API</span>
    url = <span class="hljs-string">f"https://api.ecowitt.net/api/v3/device/real_time?                    application_key=<span class="hljs-subst">{ECOWITT_APPLICATION_KEY}</span>&amp;api_key=            <span class="hljs-subst">{ECOWITT_API_KEY}</span>&amp;mac=<span class="hljs-subst">{ECOWITT_IMEI_MAC}</span>&amp;call_back=all"</span>

    <span class="hljs-comment"># Call our ecowitt api</span>
    response = requests.get(url)

    <span class="hljs-comment"># Get current time</span>
    now = datetime.datetime.now()

    <span class="hljs-comment"># Convert to JSON</span>
    data = response.json()

    <span class="hljs-comment"># Insert data into mongodb</span>
    db.ecowitt.insert_one(data)

    <span class="hljs-comment"># log info to our handler.log</span>
    logger.info(<span class="hljs-string">f"Data inserted at <span class="hljs-subst">{now}</span>"</span>)
</code></pre>
<p>With this, our python function is ready and we can start to set up a crontab. To create this cronjob we need to specify when the function is going to be executed, in my case I have chosen every minute. So now we can create a file named crontab.</p>
<pre><code class="lang-python"><span class="hljs-comment"># crontab</span>
*/<span class="hljs-number">1</span> * * * * python3 /app/handler.py
</code></pre>
<p>Now we can start to create our Dockerfile. So to create this we need a file named Dockerfile.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Dockerfile</span>
FROM python:<span class="hljs-number">3.10</span><span class="hljs-number">.9</span>-alpine

<span class="hljs-comment"># Copy files</span>
COPY crontab requirements.txt handler.py .env /app/

<span class="hljs-comment"># Set working directory</span>
WORKDIR /app

<span class="hljs-comment"># Install dependencies</span>
RUN pip install -r requirements.txt

<span class="hljs-comment"># Install crontab</span>
RUN crontab crontab

<span class="hljs-comment"># Run crontab</span>
CMD [<span class="hljs-string">"crond"</span>, <span class="hljs-string">"-f"</span>]
</code></pre>
<p>Now we can use this in a docker-compose stack with our MongoDB database.</p>
<pre><code class="lang-python"><span class="hljs-comment"># docker-compose.yaml</span>
version: <span class="hljs-string">'3'</span>

<span class="hljs-comment"># Creating a isolated network for comunications.</span>
networks:
  ecowitt:
    driver: bridge

services:
    ecowitt:
      build: ./
      container_name: ecowitt
      image: python3<span class="hljs-number">.10</span><span class="hljs-number">.9</span>-alpine
      restart: unless-stopped
      volumes:
        - appdata:/var/www
      depends_on:
        - mongodb
      networks:
        - ecowitt

    mongodb:
      <span class="hljs-comment"># You can use the latest image</span>
      image: mongo:<span class="hljs-number">4.4</span><span class="hljs-number">.6</span>
      container_name: mongodb
      restart: unless-stopped
      command: mongod --auth
      environment:
        MONGO_INITDB_ROOT_USERNAME: your_username
        MONGO_INITDB_ROOT_PASSWORD: your_password
        MONGO_INITDB_DATABASE: ecowitt
        MONGODB_DATA_DIR: /data/db
        MONDODB_LOG_DIR: /dev/null
      <span class="hljs-comment"># I have exposed ports to connect to mongodb compass</span>
      ports:
        - <span class="hljs-string">"27017:27017"</span>
      volumes:
        - mongodbdata:/data/db
      networks:
        - ecowitt

<span class="hljs-comment"># Presistent volumes so data doesn't get deleted on reboot</span>
volumes:
  mongodbdata:
  appdata:
    driver: local
</code></pre>
<p>Now when everything is ready we can use "docker-compose up -d" to deploy our application to docker. And then you have a function that collects data from your device and stores it locally on your device. If you want to monitor cronjobs and want to step it a little bit further you can checkout <a target="_blank" href="https://cronitor.io">Cronitor</a> to get emails if your function did not run and check statuses.</p>
]]></content:encoded></item></channel></rss>