Skip to content

智慧停车解决方案

方案概述

智慧停车通过 NB-IoT 地磁传感器实时监测车位状态,结合停车管理平台,实现车位引导、无感支付、数据分析等功能。

系统架构

┌─────────────────────────────────────────────────────┐
│                  感知层                               │
│  地磁传感器(NB-IoT)× N 个车位                       │
│  视频识别摄像头(可选,用于车牌识别)                   │
└─────────────────────────────────────────────────────┘
              ↓ NB-IoT 网络
┌─────────────────────────────────────────────────────┐
│                  平台层                               │
│  停车管理平台                                         │
│  ├── 车位状态实时监控                                  │
│  ├── 停车记录管理                                      │
│  ├── 费用计算与支付                                    │
│  └── 数据统计分析                                      │
└─────────────────────────────────────────────────────┘
              ↓ API
┌─────────────────────────────────────────────────────┐
│                  应用层                               │
│  车主 App(找车位/导航/支付)                          │
│  管理员 App(巡检/收费/报表)                          │
│  诱导屏(剩余车位显示)                                │
└─────────────────────────────────────────────────────┘

地磁传感器选型

推荐方案

传感器:QMC5883L(三轴地磁传感器)
  - 量程:±8 Gauss
  - 分辨率:2mG
  - 接口:I2C
  - 功耗:100μA(测量模式)

模组:BC660K-GL(NB-IoT)
  - PSM 功耗:2.5μA
  - 电池:ER14505(2700mAh 锂亚电池)
  - 预期寿命:5-8年

外壳:IP67 防水外壳
  - 材质:ABS + 不锈钢螺栓
  - 安装:路面开孔埋入(深度 50mm)

电池寿命计算

python
def calculate_battery_life():
    """计算地磁传感器电池寿命"""
    
    # 工作参数
    battery_capacity_mah = 2700  # ER14505 容量
    
    # 功耗参数
    psm_current_ua = 2.5      # PSM 睡眠电流(μA)
    active_current_ma = 15    # 活跃状态电流(mA)
    tx_current_ma = 220       # NB-IoT 发射电流(mA)
    
    # 时间参数(每次检测周期 = 5秒)
    check_interval_s = 5      # 检测间隔
    active_time_ms = 100      # 每次检测活跃时间(ms)
    tx_time_ms = 3000         # 状态变化时发送时间(ms)
    
    # 状态变化频率(假设每天平均 20 次进出)
    state_changes_per_day = 20
    
    # 每天电量消耗(mAh)
    # 检测消耗
    checks_per_day = 86400 / check_interval_s  # 17280次/天
    check_energy = checks_per_day * active_current_ma * (active_time_ms / 1000) / 3600
    
    # 发送消耗
    tx_energy = state_changes_per_day * tx_current_ma * (tx_time_ms / 1000) / 3600
    
    # 睡眠消耗
    sleep_time_s = 86400 - checks_per_day * (active_time_ms / 1000) - state_changes_per_day * (tx_time_ms / 1000)
    sleep_energy = psm_current_ua / 1000 * sleep_time_s / 3600
    
    total_daily_mah = check_energy + tx_energy + sleep_energy
    
    # 电池寿命(天)
    battery_life_days = battery_capacity_mah / total_daily_mah
    
    print(f"每日检测消耗: {check_energy:.3f} mAh")
    print(f"每日发送消耗: {tx_energy:.3f} mAh")
    print(f"每日睡眠消耗: {sleep_energy:.3f} mAh")
    print(f"每日总消耗: {total_daily_mah:.3f} mAh")
    print(f"预计电池寿命: {battery_life_days:.0f} 天 ({battery_life_days/365:.1f} 年)")

calculate_battery_life()

停车管理平台

核心数据模型

python
# Django 数据模型示例
from django.db import models

class ParkingLot(models.Model):
    """停车场"""
    name = models.CharField(max_length=100)
    address = models.CharField(max_length=200)
    latitude = models.FloatField()
    longitude = models.FloatField()
    total_spaces = models.IntegerField()
    available_spaces = models.IntegerField()
    hourly_rate = models.DecimalField(max_digits=6, decimal_places=2)
    
    def update_available_spaces(self):
        self.available_spaces = ParkingSpace.objects.filter(
            lot=self, status='free'
        ).count()
        self.save()

class ParkingSpace(models.Model):
    """车位"""
    STATUS_CHOICES = [
        ('free', '空闲'),
        ('occupied', '占用'),
        ('reserved', '预约'),
        ('disabled', '故障'),
    ]
    
    lot = models.ForeignKey(ParkingLot, on_delete=models.CASCADE)
    space_number = models.CharField(max_length=20)
    device_id = models.CharField(max_length=50, unique=True)  # 地磁传感器 ID
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='free')
    last_updated = models.DateTimeField(auto_now=True)
    
    def update_status(self, occupied):
        old_status = self.status
        self.status = 'occupied' if occupied else 'free'
        self.save()
        
        # 更新停车场可用车位数
        self.lot.update_available_spaces()
        
        # 如果状态变化,记录事件
        if old_status != self.status:
            ParkingEvent.objects.create(
                space=self,
                event_type='enter' if occupied else 'exit',
                timestamp=timezone.now()
            )

class ParkingRecord(models.Model):
    """停车记录"""
    space = models.ForeignKey(ParkingSpace, on_delete=models.CASCADE)
    license_plate = models.CharField(max_length=20, blank=True)
    enter_time = models.DateTimeField()
    exit_time = models.DateTimeField(null=True, blank=True)
    duration_minutes = models.IntegerField(null=True)
    fee = models.DecimalField(max_digits=8, decimal_places=2, null=True)
    payment_status = models.CharField(max_length=20, default='unpaid')
    
    def calculate_fee(self):
        if self.exit_time and self.enter_time:
            duration = (self.exit_time - self.enter_time).total_seconds() / 60
            self.duration_minutes = int(duration)
            
            # 计费规则:首小时 5元,之后每小时 3元
            hours = duration / 60
            if hours <= 1:
                self.fee = 5.0
            else:
                self.fee = 5.0 + (hours - 1) * 3.0
            
            self.save()

MQTT 数据接入

python
# 接收地磁传感器数据
import paho.mqtt.client as mqtt
import json
from django.utils import timezone

def on_message(client, userdata, msg):
    """处理传感器上报的数据"""
    try:
        data = json.loads(msg.payload.decode())
        device_id = data['device_id']
        occupied = data['occupied']
        
        # 更新车位状态
        space = ParkingSpace.objects.get(device_id=device_id)
        space.update_status(occupied)
        
        # 推送实时更新到前端(WebSocket)
        channel_layer.group_send(
            f"parking_{space.lot.id}",
            {
                "type": "parking.update",
                "space_id": space.id,
                "status": space.status
            }
        )
        
    except ParkingSpace.DoesNotExist:
        print(f"Unknown device: {device_id}")
    except Exception as e:
        print(f"Error processing message: {e}")

mqtt_client = mqtt.Client()
mqtt_client.on_message = on_message
mqtt_client.connect("broker.emqx.io", 1883)
mqtt_client.subscribe("parking/+/status")
mqtt_client.loop_forever()

褚成志的笔记