Skip to main content
Redhat Developers  Logo
  • AI

    Get started with AI

    • Red Hat AI
      Accelerate the development and deployment of enterprise AI solutions.
    • AI learning hub
      Explore learning materials and tools, organized by task.
    • AI interactive demos
      Click through scenarios with Red Hat AI, including training LLMs and more.
    • AI/ML learning paths
      Expand your OpenShift AI knowledge using these learning resources.
    • AI quickstarts
      Focused AI use cases designed for fast deployment on Red Hat AI platforms.
    • No-cost AI training
      Foundational Red Hat AI training.

    Featured resources

    • OpenShift AI learning
    • Open source AI for developers
    • AI product application development
    • Open source-powered AI/ML for hybrid cloud
    • AI and Node.js cheat sheet

    Red Hat AI Factory with NVIDIA

    • Red Hat AI Factory with NVIDIA is a co-engineered, enterprise-grade AI solution for building, deploying, and managing AI at scale across hybrid cloud environments.
    • Explore the solution
  • Learn

    Self-guided

    • Documentation
      Find answers, get step-by-step guidance, and learn how to use Red Hat products.
    • Learning paths
      Explore curated walkthroughs for common development tasks.
    • Guided learning
      Receive custom learning paths powered by our AI assistant.
    • See all learning

    Hands-on

    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.
    • Interactive labs
      Learn by doing in these hands-on, browser-based experiences.
    • Interactive demos
      Click through product features in these guided tours.

    Browse by topic

    • AI/ML
    • Automation
    • Java
    • Kubernetes
    • Linux
    • See all topics

    Training & certifications

    • Courses and exams
    • Certifications
    • Skills assessments
    • Red Hat Academy
    • Learning subscription
    • Explore training
  • Build

    Get started

    • Red Hat build of Podman Desktop
      A downloadable, local development hub to experiment with our products and builds.
    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.

    Download products

    • Access product downloads to start building and testing right away.
    • Red Hat Enterprise Linux
    • Red Hat AI
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat Developer Toolset

    References

    • E-books
    • Documentation
    • Cheat sheets
    • Architecture center
  • Community

    Get involved

    • Events
    • Live AI events
    • Red Hat Summit
    • Red Hat Accelerators
    • Community discussions

    Follow along

    • Articles & blogs
    • Developer newsletter
    • Videos
    • Github

    Get help

    • Customer service
    • Customer support
    • Regional contacts
    • Find a partner

    Join the Red Hat Developer program

    • Download Red Hat products and project builds, access support documentation, learning content, and more.
    • Explore the benefits

Visualizing Smog Sensor Data with the help of Vert.x, Prometheus, and Grafana

July 6, 2017
Heiko Rupp

    Air pollution is a major problem in many cities around the globe. Some people in Stuttgart, Germany have developed cheap smog sensors that people can install on their balconies and other convenient places and then report data to a central site. I have written about that on OpenSource.com. The data is sent to a central server, from where it is visualized on a map. At the time of writing the above article, there was no way of seeing how the value has changed over time. Meanwhile, there is a visualization of the last 24 hours available on the map.

    The sensor is also able to send data to an additional target, for example, a local database. Thus, I decided to feed the data to a local server for long-term storage to visualize trends.

    As I was playing with Prometheus at this time, I thought that feeding the data into it may be a good use case for further exploration. Now that Prometheus wants to scrape the data and the sensor is only pushing the data, it became clear that I need an intermediate gateway that solves this mismatch and which also translates the data format the sensor sends into the format Prometheus expects.

    To implement the gateway, I choose Vert.x a modern day reactive framework that runs on the Java Virtual Machine (JVM). I was first considering other options, but it turned out that Vert.x' implicit handling of connections and threading made my life easy.

    The gateway receives Http POST requests from the sensor with measurement data in InfluxDB format. It exposes the data to GET requests on /metrics in the Prometheus text format.

    Finally, the data stored in Prometheus is visualized via Grafana.

    I will now show some pieces of the code; the full code is available on GitHub.

    Gateway code

    The code consists of two main parts for the two endpoints described above.
    I have implemented both in the same Verticle.

    public class MainVerticle extends AbstractVerticle {
    
      // Label on dust data
      private static final String TYP_FS = "{typ=\"fs\"}";
    
      @Override
      public void start(Future fut) {
    
        // [... see below ...]
    
        vertx
            .createHttpServer()
            .requestHandler(router::accept)
            .listen(
                // Set the port we listen on to 10080
                config().getInteger("http.port", 10080),
                result -> {
                  if (result.succeeded()) {
                    fut.complete();
       [...]

    This first part creates a new verticle and then inside of start() sets the http port it listens on to 10080 and then tells Vert.x that the configuration is ready. Vert.x then starts is accept loop and dispatches incoming requests.

    The next step is now to define handlers for the endpoints to do the actual work. In the handlers we need to be careful not to block or implement slow operations; Vert.x may decide to abort the handler in this case.

    Let's look at the handler for scraping of data first:

    router.get("/metrics")
              .handler(routingContext -> {
    
          HttpServerResponse response = routingContext.response();
    
          // If we have no data yet, return a 204 'no content'
          if (values.isEmpty()) {
            response.setStatusCode(204).end();
            return;
          }
    
          // Construct the response
          StringBuilder builder = [...]
          // send it back
          response.setStatusCode(200)
              .putHeader("content-type","text/plain; version=0.0.4")
              .end(builder.toString());
        });

    Now let's look at the POST handler. This is a tiny bit more complicated as we need to explicitly tell Vert.x to that we want to obtain the body of the request. On top, we also want to get the sensor ID, which is encoded in a Http-Header.

    // We need the body, so we need to enable it.

    // We need the body, so we need to enable getting it.
        router.route("/").handler(BodyHandler.create());
    
        // Bind "/" to our fs-input
        router.post("/")
              .handler(routingContext -> {
          // Get the sensor id from the header
          String tmp = routingContext.request().getHeader("X-Sensor");
    [...]
          // Get the measurement data
          JsonObject body_json = routingContext.getBodyAsJson();
          JsonArray value_array = body_json.getJsonArray("sensordatavalues");
    [...]
          HttpServerResponse response = routingContext.response();
          response.setStatusCode(200).end();

    Building and running the code

    You can check out the full code from GitHub and then build it via,

    $ mvn install

    This creates a self-contained Java archive in the target directory, which contains our Verticle along with all the Vert.x code that is needed to run it. Thus, running is as simple as:

    $ java -jar target/fsgw.jar

    Configuring the other pieces

    For the setup, I run the Gateway, Prometheus, and Grafana on the same host, with an IP of 172.31.7.2.

    For the sensor

    Go to the sensor configuration page, select "Send to own API" and enter the IP and port of the Gateway like this:

    Sensor configuration

    After this is done, save the configuration and reboot the sensor.

    Prometheus

    Prometheus needs an external configuration file prometheus.yml that gets an additional scrape config for our sensor:

    scrape_configs:
      - job_name: 'feinstaub'
        scrape_interval: 30s
    
        static_configs:
          - targets: ['172.31.7.2:10080']
    

    As the target, you enter the IP address and port from the Vert.x gateway. After this is done, you can start Prometheus and pass the path to the configuration to it:

    $ prometheus -config.file /usr/local/etc/prometheus.yml

    Grafana

    Start Grafana and point your browser at port 3000; default login is admin/admin.
    To set up Grafana, one needs to define a datasource of type Prometheus that points to the Prometheus server at http://localhost:9090/. Once this is done, we can set up a new dashboard and add graphs to it.

    In above screenshot, you see the query editor. As the code in the gateway is set up to put labels on the exported items according to the type (the sensor can also report temperature and humidity), it is possible to query for the values with a label query of {{typ="fs"}}.

    Summary

    The article shows an end-to-end example of an IoT device sending data in a certain format. A gateway is implemented with the help of the Vert.x framework, which does all the magic of connection handling etc.
    Finally, the data is stored in a Prometheus time series database and graphed via Grafana.


    Download the Eclipse Vert.x cheat sheet, this cheat sheet provides step by step details to let you create your apps the way you want to.

    Last updated: June 30, 2017

    Recent Posts

    • Every layer counts: Defense in depth for AI agents with Red Hat AI

    • Fun in the RUN instruction: Why container builds with distroless images can surprise you

    • Trusted software factory: Building trust in the agentic AI era

    • Build a zero trust AI pipeline with OpenShift and RHEL CVMs

    • Red Hat Hardened Images: Top 5 benefits for software developers

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Platforms

    • Red Hat AI
    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Build

    • Developer Sandbox
    • Developer tools
    • Interactive tutorials
    • API catalog

    Quicklinks

    • Learning resources
    • E-books
    • Cheat sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site status dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2026 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Chat Support

    Please log in with your Red Hat account to access chat support.