In a world where IoT and web are increasingly converging, the ability to create real-time monitoring interfaces is becoming crucial. Through this practical tutorial, we will explore creating a complete traffic light monitoring system, combining the power of Zephyr OS for IoT with modern web technologies. This project will serve as a concrete example to understand the challenges and solutions of real-time IoT monitoring.
Note: As a Zephyr OS expert, I am available to support you in your IoT development projects. Feel free to contact me by email or on LinkedIn or via GitHub for any questions about Zephyr OS or to discuss your embedded development needs.
The complete source code for this project is available on GitHub.
Article Outline
-
Project Overview
- Global architecture
- Technologies used
- Learning objectives
-
IoT Part: Traffic Light Controller
- Introduction to Zephyr OS
- Controller implementation in C++
- Server communication
-
Backend: Servers and Communication
- HTTP API with Bun
- WebSocket server for real-time
- State management with Redis
-
Frontend: Monitoring Interface
- Building with Next.js 15
- Real-time React components
- State and updates management
-
Infrastructure and Deployment
- Docker configuration
- Development scripts
- Production deployment
-
Going Further
- Tests and Quality
- Monitoring and Observability
- Functional Improvements
Introduction
Real-time monitoring of IoT devices presents unique challenges, from state management to bidirectional communication. Our connected traffic lights project perfectly illustrates these issues: how to ensure reliable synchronization between physical devices and a web interface while maintaining optimal performance?
Project Objectives
This educational project aims to:
- Demonstrate integration between IoT and modern web technologies
- Explore real-time communication patterns
- Put into practice full-stack development best practices
- Understand IoT supervision challenges
Global Architecture
Our system is built around four main components:
- IoT Controller: Developed with Zephyr OS in C++, it simulates a traffic light controller
- API Gateway: HTTP server for controller communication
- WebSocket Server: Ensures real-time distribution of state changes
- Web Interface: Next.js application for visualization and control
Important note about simulation: In this project, we simulate the IoT device in a Docker container for educational purposes. The controller simply logs state changes. In a real deployment, this controller would be installed on an actual IoT device (like a Raspberry Pi Pico) and would physically control traffic lights via its GPIO.
Example with Raspberry Pi Pico
The Raspberry Pi Pico is an excellent choice for implementing this project in real conditions because:
- It officially supports Zephyr OS
- It has GPIO to control the traffic light LEDs
- It can be connected to the network via various long-range communication modules (LoRaWAN, NB-IoT, LTE-M) suitable for outdoor deployments
- Its cost is very affordable (around €5)
To move from our simulation to a real deployment, you would need to:
- Replace logs with GPIO commands
- Adapt network configuration for WiFi or long-range communication modules (LoRaWAN, NB-IoT, LTE-M) depending on deployment context
- Manage power supply and resilience
- Add protective casing
1. Project Overview
Global Architecture
Our traffic light monitoring system relies on a modern distributed architecture, designed to ensure reliable real-time communication between IoT devices and the user interface.
Data Flow
-
IoT Level
- Traffic light controllers, based on Zephyr OS, manage light states
- In our implementation, state changes are transmitted via HTTP to the API Gateway, but other protocols could have been used:
- MQTT for lighter and optimized IoT communication
- CoAP for constrained networks
- LoRaWAN for long-range communication
- gRPC for increased performance
- Controllers maintain a robust connection with the server
-
Backend Level
- API Gateway receives updates and stores them in Redis
- Redis acts as a centralized state store
- WebSocket server subscribes to Redis events
- Changes are broadcast in real-time to connected clients
-
Frontend Level
- Next.js application establishes WebSocket connection
- React components update automatically
- Interface displays real-time light states
Technologies Used
IoT Side
Backend and Communication
Frontend
Learning Objectives
This project has been designed to cover several essential aspects of modern IoT and web development:
1. Embedded Programming
- Using Zephyr OS for IoT development
- State and transition management in C++
- Network communication from an embedded device
2. Distributed Architecture
- Communication between heterogeneous systems
- Distributed state management with Redis
- Real-time messaging patterns
3. Modern Web Development
- Hexagonal architecture with Next.js
- Performant React components
- TypeScript and strong typing
4. DevOps and Infrastructure
- Containerization with Docker
- Automation scripts
- Monitoring and logging
In the following sections, we'll explore in detail each component of the system, starting with the IoT controller based on Zephyr OS.
2. IoT Part: Traffic Light Controller
Introduction to Zephyr OS
Zephyr OS is an open-source real-time operating system (RTOS), particularly suited for embedded and IoT systems. In our project, it offers several key advantages:
- Real-time management: Perfect for precise traffic light control
- Robust network stack: Native TCP/IP protocol support
- Reduced memory footprint: Ideal for constrained devices
- Modern C++ support: Enables object-oriented programming
Controller Implementation
Our traffic light controller is implemented in modern C++, using Zephyr OS features for efficient state management and communication.
Code Structure
State Management
Server Communication
Communication with the backend server is handled by a dedicated class using Zephyr's HTTP API.
HTTP Client
Logging and Monitoring
Traffic Light Management Algorithm
The algorithm implemented in main.cpp
manages the traffic light cycle in a safe and coordinated manner. We opted for a simple and demonstrative implementation that could be enhanced for more complex use cases.
-
System Initialization
-
Main Cycle
- The system alternates between North-South and East-West axes
- Each cycle includes three phases:
- Green (30 seconds)
- Yellow (5 seconds)
- Red with safety delay (2 seconds)
-
State Change Management
-
Asynchronous Communication
- A dedicated thread handles HTTP state change sending
- Events are queued via
k_msgq
- HTTP thread processes them asynchronously
-
Safety and Robustness
- Safety delay between axis changes
- Communication error handling
- Event logging for monitoring
Improvement Paths
This basic implementation could be enhanced with:
-
Customizable Scenarios
- Time-based duration configuration
- Special modes (night, emergency, events)
- Real-time traffic adaptation
-
Advanced Traffic Management
- Vehicle presence detection
- Public transport priority
- Intersection synchronization
-
Dynamic Configuration
- Remote parameter interface
- On-the-fly scenario changes
- Traffic pattern machine learning
To implement these improvements, we would need to:
- Add an abstraction layer for scenarios
- Implement a dynamic configuration system
- Integrate sensors and complex business rules
- Develop a more complete control API
This simple version remains perfectly suited to demonstrate basic IoT and real-time communication concepts.
Project Configuration
The prj.conf file configures Zephyr OS features for our project. This configuration enables:
- C++ and C++17 standard support to use modern language features
- Network capabilities with IPv4 and TCP for server communication
- Sockets and HTTP client to send state updates
- Logging system for debugging and monitoring
These options are essential for our IoT controller to communicate over the network and send traffic light state changes to the central server.
Optimized Compilation with Zephyr OS
Unlike traditional operating systems like Linux that include many default modules and drivers, Zephyr OS uses a minimalist and highly configurable approach. During compilation, only strictly necessary components are included in the final image:
-
Difference from Traditional OS
- A classic embedded Linux is several hundred MB
- It includes many unused drivers and services
- Startup loads many superfluous components
- Attack surface is larger
-
Zephyr Approach Advantages
- Final image is only a few hundred KB
- Only configured drivers and protocols are included
- Startup is nearly instantaneous
- Attack surface is minimal
-
Granular Configuration
- Each feature is a Kconfig module
- Dependencies are automatically resolved
- Optimization is maximized
- Resources are statically allocated
This "from scratch" approach allows obtaining a highly optimized and secure system, perfectly adapted to IoT constraints:
- Limited resources (RAM/Flash)
- Minimal energy consumption
- Fast startup
- Reduced attack surface
Compilation and Deployment
The project uses CMake for compilation:
This IoT implementation illustrates several advanced concepts:
-
Event-Driven Programming
- Use of message queues for inter-thread communication
- Timers for state transition management
-
Resource Management
- Efficient memory usage
- Network connection management
-
Robustness
- Detailed event logging
- Communication error handling
- Automatic reconnection
In the next section, we'll see how the backend handles communication with these IoT controllers and distributes updates to web clients.
3. Backend: Servers and Communication
Our backend consists of several services working together to ensure smooth communication between IoT controllers and the web interface.
API Gateway with Bun
The API Gateway is the entry point for IoT controllers. Implemented with Bun for its exceptional performance, it handles HTTP requests and maintains state consistency.
Request Management
WebSocket Server
The WebSocket server ensures real-time distribution of updates to connected web clients.
Server Implementation
State Management with Redis
Redis plays a central role in our architecture, serving both as a message broker and state store.
Redis Configuration
Redis Subscriber
Communication Architecture
Our backend implements several essential communication patterns:
-
Pub/Sub Pattern
- Redis as message broker
- Decoupling of producers and consumers
- Efficient update distribution
-
Gateway Pattern
- Single entry point for IoT devices
- Data validation and transformation
- Centralized error handling
-
Observer Pattern
- Real-time change notification
- WebSocket connection maintenance
- Update distribution to clients
Security and Performance
Several measures are in place to ensure security and performance:
-
Security
- Input data validation
- Configured CORS headers
- Network isolation with Docker
-
Performance
- Using Bun for optimal performance
- Persistent Redis connections
- Efficient WebSocket management
-
Reliability
- Event logging
- Robust error handling
- Automatic service reconnection
In the next section, we'll explore the user interface developed with Next.js that allows visualization and interaction with our traffic light system.
4. Frontend: Monitoring Interface
Our system's user interface is built with Next.js 15, following modern development best practices and a hexagonal architecture.
Frontend Architecture
Our application follows a hexagonal architecture (ports and adapters) to maintain a clear separation of concerns:
Adapter Implementation
The adapter handles communication with the backend via WebSocket:
React Components
Main Page
Traffic Light Component
Styles and Configuration
Tailwind Configuration
Optimizations and Best Practices
-
Performance
- Use of React Server Components
- Render optimization
- Lazy loading of non-critical components
-
Accessibility
- Keyboard support
- Appropriate ARIA attributes
- Optimized color contrast
-
Maintainability
- Hexagonal architecture
- Strict typing with TypeScript
- Automated testing
In the next section, we'll cover the infrastructure and deployment of our application.
5. Infrastructure and Deployment
Our system uses Docker to ensure consistent and reproducible deployment across all environments.
Docker Configuration
Service Composition
Development Scripts
Service Management Script
Development Environment Configuration
Docker Image for Zephyr
Support Services
Docker Services Script
Dependency Management
Next.js Configuration
Deployment Best Practices
-
Secret Management
- Use of environment variables
- Separation of configurations by environment
- Secure secret storage
-
Monitoring
- Centralized logging
- Performance metrics
- Automated alerts
-
Security
- Network isolation
- Regular dependency updates
- Vulnerability scanning
In the final section, we'll discuss testing strategies and monitoring of our application.
6. Going Further
To make this project more robust and production-ready, several improvement areas can be explored:
1. Tests and Quality
To ensure system reliability, we should implement:
IoT Controller Tests
- Unit tests for traffic light state machine
- Network integration tests
- Error condition simulation
- Light sequence validation
Frontend Tests
- React component tests with Jest and Testing Library
- End-to-end tests with Cypress or Playwright
- Performance tests with Lighthouse
- Accessibility validation
2. Monitoring and Observability
For effective production monitoring, we should add:
-
Performance
- Integration with Prometheus/Grafana
- Detailed WebSocket metrics
- IoT resource monitoring
-
Reliability
- Controller heartbeat system
- Automatic anomaly detection
- Automatic state backup
-
Security
- Controller authentication
- Communication encryption
- Access auditing
3. Functional Improvements
The system could be enhanced with:
-
Advanced Interface
- Maintenance mode
- State change history
- Customizable dashboards
-
Scenario Management
- Time-based scheduling
- Special modes (emergency, events)
- External integration API
-
Scalability
- Multi-intersection support
- Intersection synchronization
- Load balancing
4. Energy Optimization for Battery Deployment
For projects requiring energy autonomy (isolated sites, areas without mains power), several optimizations would be necessary:
-
Power Modes
- Normal mode for standard operation
- Eco mode for energy saving during quiet days
- Night mode with reduced brightness
- Emergency mode for low battery
-
Energy Saving Strategies
- CPU sleep between state changes
- Network transmission grouping
- Dynamic LED brightness adjustment
-
Solar Power
- Appropriate panel sizing
- LiFePO4 batteries for longevity
- Backup system
-
Battery Monitoring
For successful deployment, it is recommended to:
- Continuously monitor battery health
- Plan preventive replacements
- Regularly clean solar panels
- Implement degraded modes for low battery
- Provide backup signaling
Conclusion
This project demonstrates the successful integration of IoT and modern web technologies to create a real-time monitoring system. Key takeaways include:
-
Distributed Architecture
- Clear separation of responsibilities
- Efficient component communication
- Scalability and maintainability
-
Modern Technologies
- Zephyr OS for IoT
- Next.js for frontend
- WebSocket for real-time
-
Best Practices
- Automated testing
- Complete monitoring
- Detailed documentation
This project can serve as a foundation for developing more complex IoT applications by adapting the architecture and patterns used according to your specific needs.
Putting into Practice
To get the most out of this tutorial and develop your own IoT projects, here are some practical exercise suggestions:
1. Start Small
-
Simplified Version
- First create a single traffic light
- Use a simple HTTP server without WebSocket
- Display the state in a basic web page
-
IoT Simulation
- Start without physical hardware
- Simulate the controller with a Node.js script
- Test communication logic
2. Progressive Evolution
-
Add WebSockets
- Implement real-time updates
- Handle automatic reconnection
- Add logs to understand the flow
-
Integrate Redis
- First store simple states
- Add data persistence
- Implement pub/sub patterns
3. Project Variations
Here are some ideas to create your own version:
-
Other Use Cases
- Temperature/humidity monitor
- Smart lighting system
- Automatic watering control
-
Alternative Technologies
- Replace Zephyr OS with ESP32/Arduino
- Use MQTT instead of WebSockets
- ...
4. Additional Resources
To deepen your understanding of each aspect:
-
Official Documentation
-
Example Repositories
-
Communities