- 积分
- 673
- 金钱
- 598
- 威望
- 0
- 贡献
- 0
- HASS币
- 10
高级会员
- 积分
- 673
- 金钱
- 598
- HASS币
- 10
|
本帖最后由 shenbo 于 2024-1-9 13:00 编辑
背景:家里买了Tesla后就很羡慕老婆可以通过手机控制车辆解锁的便捷,特别是用Tesla Custom Integration集成,将车辆接入了HA,便开始一直琢磨如何将自己的车也接入HA,最后通过使用ESPHOME的MQTT模式+车载WIFI实现了通过HA远程控制车锁、GPS等功能,但在这个方式下WIFI路由器加上ESP32模块耗电量惊人,达到4-5w的功率,哪怕我是混动车,每天晚上停车的时候还是要插上充电桩才安心(曾经某个假期出去玩忘记充电,5天回来,车电瓶就挂了),此外,车载Wifi的稳定性也一般,所以一直在琢磨如何优化,可最无奈的是ESPHOME没有GPRS的组件提供使用,所以用ESPHOME无法实现ESP32+GPRS模块的方式接入HA。经过查阅资料后发现,其实ESP32+GPRS+MQTT是非常常见的iot方案,还有很多成熟的开发板,只是需要用C语言和Arduino IDE来开发,我抱着试一试的心态买了Lilygo-Tsim7600G-h这个开发板,于是有了这个帖子。
先来简单介绍一下Lilygo-Tsim7600G-h这个产品,其实他就是将ESP32模块和SIM7600模块连接在了一起,并加入了18650供电和太阳能充电功能,我经过整个折腾的过程后发现,其实完全没有必要买SIM7600这个4G模块,2G模块的速度对于MQTT来说足以,如果买SIM800自己焊不超过100元全部搞定,计算买lilygo的2G成品SIM开发板也就100多够了,我这个买贵了花了300大洋,不过这里要注意一个问题不是所有的Modem模块都有GPS芯片,我这款是包涵的如果买SIM800,请单独再额外买一个GPS模块。
先上一下最终完成后的硬件图片和HA控制面板--------
Mushcard美化后的控制面板
硬件设备(不会做PCB板,请忽略杂乱的连线)
MQTT接入的原始HA控制界面
开发过程-------------
【硬件清单】
1、Lilygo TSIM7600g-h
2、PN532读卡模块(后来考虑功耗被我去除了,改用ESP32的BLE服务来解决如果没有GRPS信号无法通过HA控制解锁的问题)
3、6路5V继电器(其实感觉用光耦能更小巧,我这个继电器是之前用在ESPHOME控制车锁的设备里,由于和车钥匙连接好了,懒得换)
4、车钥匙(这个是项目最核心,也是最土的地方,是没办法的办法,由于车没有远程控制的设计,所以只能控制车辆自身的钥匙来实现,当然这个方式自然也成了万能方式)
-------欢迎对这个问题拍砖,有什么更好的方法改进
5、INA219模块(测量车辆电瓶电压及整个设备的功耗)
6、12V转5V变压模块(给5v设备供电)
7、5V转3.3V I2C中继芯片(连接PN532使用)
9、震动传感器(唤醒ESP32使用)
10、BLE开关(唤醒ESP32使用,解决脱离ESP32解锁,解决iPhone BLE连接等问题,后续详解)
11、尺寸合适的洞洞板、连接线、接头若干、2032电池盒一个
【功能清单】通过直接调用GRPS模块,设备工作的能耗大概1.5w左右,对比之前的4-5w大幅度下降,睡眠后基本0能耗(电流消耗小于10ma)
1、MQTT连入HA远程控制原有车钥匙的所有功能
2、通过连接车辆关闭后备箱按钮实现MQTT连入HA远程关闭后备箱
3、远程关闭车钥匙电源(只是简单的关闭车钥匙的电池连接)
4、MQTT连入HA,实现车辆GPS轨迹记录
5、硬件设备在车辆停止或手机离开车辆一定时间后进入睡眠状态(该状态下电流消耗小于10ma),车辆轻微震动(轻拍车身)或者重新连接手机BLE后,立刻5s内唤醒,该功能通过HA控制关闭、开启
6、没有GPRS信号时可以通过手机BLE,解/锁车辆,并支持调整解/锁车辆的BLE RSSI信号强度,该功能通过HA控制关闭、开启
7、没有GPRS信号时可以通过NFC,解/锁车辆(需要PN532,我个人考虑能耗,只用了BLE,PN532需要20ma的电流),该功能通过HA控制关闭、开启
8、洗车或代客泊车时,使用Beacon蓝牙信标或NFC(需要PN532)解/锁车辆
9、MQTT连入HA监测车辆电瓶电压及设备能耗
10、向指定手机发SMS报告状态或通过MQTT读取设备SIM卡收取的短信
11、所有实体配置MQTT Discovery,HA自动创建设备及实体
12、HA给出的所有指令,存入ESP32的NVS,ESP32重启的时候自动重载
13、Wifi OTA 升级
14、ESP32 Watch DOG 死机重启
【硬件连接简单展示】
车钥匙
INA219及I2C中继
装车后效果(请再次忽略乱七八糟的线路)
【Arduino IDE中对于我比较坑的代码】首先申明我是编程小白,这是我第一个编程,更是第一个C编程,拍砖请轻一点
需要用的库#include <esp_task_wdt.h>
#include <TinyGsmClient.h>
#include <ubSubClient.h>
#include <TinyGPS++.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include <references.h>
#include <INA219.h>
#include <WiFi.h>
#include <ArduinoOTA.h>
#include <NimBLEDevice.h>
#include <NimBLEAdvertisedDevice.h>
#include "utilities.h"
MQTT Discovey的配置模版(jsonString是真好用,否则代码看花眼)
void publishBeaconrssiDiscovery() {
DynamicJsonDocument doc(1024);
// Add data to the JSON document
doc["dev_cla"] = "signal_strength";
doc["unit_of_meas"] = "dB";
doc["stat_cla"] = "measurement";
doc["stat_t"] = "LilygoTSIM1/beacon_rssi";
doc["name"] = "Beacon Key RSSI";
doc["avty_t"] = "LilygoTSIM1/status";
doc["uniq_id"] = "beacon_key_rssi";
JsonObject dev = doc.createNestedObject("dev");
dev["ids"] = "08b61f3b931a";
dev["name"] = "lilygo_tsim1";
dev["sw"] = "benson v2023.12.11";
dev["mdl"] = "lilygo_tsim7600";
dev["mf"] = "lilygo";
dev["sa"] = "";
// Serialize JSON document to a string
String jsonString;
jsonString = "";
serializeJson(doc, jsonString);
// Publish the JSON string to the MQTT topic
client.publish("homeassistant/sensor/LiygoTSIM1/beaconrssi/config", jsonString.c_str(), true);
}
MQTT订阅主题处理
// 处理LOCK状态的主题
if (strcmp(topic, topicLockcommand) == 0) {
if (payload[0] == 'L') {
digitalWrite(S2_PIN, HIGH);
client.publish(topicLockstate, "LOCKED", true);
delay(500);
digitalWrite(S2_PIN, LOW);
carlocked = true;
} else if (payload[0] == 'U') {
digitalWrite(S1_PIN, HIGH);
client.publish(topicLockstate, "UNLOCKED", true);
delay(500);
digitalWrite(S1_PIN, LOW);
carlocked = false;
}
}
GPS处理(这是我编写的第一个难点,搞了好久,不过经历这个后,弄懂了GPS NVME的好多规则)
void handleGPS() {
delay(100);
//static String currentLine = "";
while (SerialAT.available() > 0) {
gps.encode(SerialAT.read());
}
if (millis() - gpslastUploadTime >= 5000) {
gpslastUploadTime = millis();
if (gps.location.isValid()) {
DynamicJsonDocument doc(1024);
// Add data to the JSON document
doc["satellites"] = gps.satellites.value();
doc["gps_accuracy"] = gps.hdop.hdop();
doc["latitude"] = formatFloat(gps.location.lat(), 6);
doc["longitude"] = formatFloat(gps.location.lng(), 6);
doc["altitude"] = formatFloat(gps.altitude.meters(), 0);
doc["course"] = formatFloat(gps.course.deg(), 0);
doc["speed"] = formatFloat(gps.speed.kmph(), 0);
// Serialize JSON document to a string
String jsonString;
jsonString = "";
serializeJson(doc, jsonString);
// Publish the JSON string to the MQTT topic
client.publish(topicGPS, jsonString.c_str(), true);
} else {
Serial.println("GPS未准备好");
client.publish("LilygoTSIM1/gps_location/staus", "GPS Not Ready");
}
}
}
BLE代码,也是难点
//BLE设置及服务
NimBLEDevice::setPower(ESP_PWR_LVL_P9);
NimBLEDevice::init("Lilygo_BLE"); // 初始化 BLE 设备
NimBLEDevice::setSecurityAuth(true, true, true);
NimBLEDevice::setSecurityPasskey(xxxxx); //BLE连接配对密码
NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_ONLY);
NimBLEServer* pServer = NimBLEDevice::createServer();
NimBLEService* pService = pServer->createService(SERVICE_UUID);
NimBLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::WRITE_AUTHEN);
pCharacteristic->setCallbacks(new MyCharacteristicCallbacks());
pService->start();
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
pAdvertising->addServiceUUID(pService->getUUID());
pAdvertising->start();
//BeaconScan设置
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(150);
pBLEScan->setWindow(80); // less or equal setInterval value
-----------------
好了,先写到这吧,欢迎有兴趣的朋友多多交流
|
评分
-
查看全部评分
|