SmartShed Smart Greenhouse
A complete smart agriculture IoT control system.
From sensor data acquisition to real-time mobile control — the full pipeline, built from scratch.
Dual-Board Modular Design
The Environment Sensing Board collects temperature, humidity, and light data. The Soil Actuation Board controls fans and water pumps. Two Hi3861 dev boards run independently and work in tandem.
Self-Implemented MQTT Client
The HarmonyOS app doesn't rely on any third-party library — it builds MQTT protocol packets manually from scratch on top of TCP Socket.
Dual-Mode Switching
Manual mode lets you freely adjust every device level. Smart mode automatically executes strategies based on sensor data.
OpenAtom Competition
Recognized in the "OpenHarmony-based Smart Greenhouse" track of the OpenAtom Competition.
How It Works
Three-layer architecture: Hardware Collection → Cloud Relay → Mobile Control
Embedded Side
Hi3861 × 2
Sensor sampling + OLED display
PWM/GPIO actuator control
EMQX Broker
MQTT 3.1.1
Public network message relay
Topic routing & dispatch
HarmonyOS App
Mate 70 Pro+ / iPad
Real-time data display
Manual / Smart dual-mode
Embedded Side: Two Boards, Each with a Job
Built on OpenHarmony LiteOS-M + CMSIS-RTOS multi-threading, developed in pure C
Environment Sensing Board (env_rgb_board)
Responsible for "seeing" and "displaying"
- AHT20 — I2C reads temperature & humidity
- Light sensor — ADC sampling (0~4095)
- RGB LED grow light — PWM control (0~100%)
- Status LEDs — GPIO 11(green) / GPIO 12(yellow)
SSD1306 OLED screen (128×64) refreshes temperature, humidity, and light data in real time
Soil Actuation Board (soil_actuator_board)
Responsible for "sensing soil" and "taking action"
- Soil moisture sensor — ADC samples water content
- DC fan — PWM four levels (off/low/medium/high)
- Submersible pump — GPIO four levels (off/small/medium/large)
Multi-Threading Task Scheduling
CMSIS-RTOS manages 4 parallel threads, mutex locks protect shared resources:
ADC/I2C sampling per second
Renders data to screen
JSON → EMQX Broker
Commands → PWM/GPIO
App Side: HarmonyOS NEXT Full-Featured Control Terminal
100% ArkTS · HDS Advanced Visual Effects · Self-Implemented MQTT Client
UI Design: Not Just Functional, But Beautiful Too
Integrated with HarmonyOS Design System (HDS) official advanced visual component library:
Immersive light-field effect top nav with natural background blending transitions
Elastic deformation + light field diffusion feedback on button press
Staggered delay spring-curve entry animations for maximum visual depth
Manual Mode (ManualPage)
Control it however you want
- Slider drag adjustment: Fan (0-3 levels) / Pump (0-3 levels) / Grow light (0-100%)
- Auto-syncs current levels to board when entering the page
- Haptic feedback vibration toggle support
Smart Mode (AutoPage)
Let the system decide for you
- Configure upper/lower threshold limits for temperature / humidity / light intensity / soil moisture
- Polls sensor data on a timer, auto-triggers control when thresholds are exceeded
- Background resident management thread (autoManagerThread), safely destroyed on page exit to prevent memory leaks
Technical Highlight: Building an MQTT Client From Scratch
The HarmonyOS app uses zero third-party MQTT libraries — it builds protocol packets entirely from TCP Socket:
- Manually concatenates Fixed Header + Variable Header + Payload
- Full implementation of CONNECT / PUBLISH / SUBSCRIBE / PINGREQ packets
- 60s interval KeepAlive heartbeat for connection persistence
- Auto-reconnect on disconnect + exponential backoff strategy
- Single TCP connection with multi-Topic subscription & routing dispatch
- @StorageLink state management decoupled from ArkUI reactive updates
The Bugs I Hit & How I Fixed Them
After MQTT async callbacks return new data, ArkUI's @ObjectLink only watches first-level property changes on objects. The result: sensor numbers wouldn't update, sliders got locked and couldn't be dragged.
this.zone1 = { ...this.zone1 }
Used shallow copy destructuring assignment to force-create a new object reference, breaking through the state machine to trigger a UI refresh. One line of code fixed a critical bug.
How Data Flows
Two one-way channels: sensor data goes up, control commands come down
Upstream: Data Acquisition → Mobile Display
① Sensor Sampling
ADC reads light/soil moisture, I2C reads AHT20 temperature & humidity
② OLED Local Display
SSD1306 screen refreshes data in real time (visible even without a phone connected)
③ JSON Serialization & Publish
Compact payload like {"intensity": 450}, published to EMQX via Paho MQTT
④ App Parse & UI Refresh
MQTT callback → shallow copy destructuring → triggers ArkUI state machine to update displayed numbers
Downstream: User Action → Hardware Execution
① User Action or Auto Strategy
Manual slider drag / Smart mode threshold judgment triggers command
② MQTT Packet Build & Send
Self-implemented client manually assembles PUBLISH packet, delivered via EMQX
③ Hi3861 Receive & Execute
MQTT callback parse → PWM adjusts fan/grow light, GPIO controls water pump
Reliability Design
5-second timeout without data marks the board as offline
UI auto-switches to gray disabled state + reconnection prompt
Auto re-subscribes to Topics upon recovery
GlobalLogBus event bus records all operations
MQTT communication status / user actions / error messages
Convenient for debugging and troubleshooting
Communication Protocol: MQTT Topic Design
Namespaced by dual-board separation, QoS 0 lightweight transmission
Upstream: Sensor Data Reporting
Downstream: Control Command Dispatch
Performance Optimization
- Compact JSON Payload — Strips redundant nesting, reduces public network transmission latency and packet loss rate
- Single-Partition Flat Architecture — Converges high-frequency concurrency into single-node communication, reducing Broker instantaneous handshake load