import os
import time
import threading
import RPi.GPIO as GPIO
import cv2
import numpy as np
import pyaudio
import vosk
import json
import serial
import pynmea2
import datetime
import sqlite3
from pathlib import Path
import logging
import sys
# ------------------- 硬件与模型配置 -------------------
BUZZER_PIN = 18 # BCM模式
FREQ_LOW = 1000
FREQ_HIGH = 2000
BUZZER_DURATION = 60 # 蜂鸣器持续秒数
PIR_PIN = 17 # BCM模式
FACE_CASCADE_PATH = '/home/pi/.local/lib/python3.7/site-packages/cv2/data/haarcascade_frontalface_alt2.xml'
PROFILE_CASCADE_PATH = '/home/pi/.local/lib/python3.7/site-packages/cv2/data/haarcascade_profileface.xml'
VOSK_MODEL_PATH = "/home/pi/vosk-model-small-cn-0.22"
# ------------------- 全局变量 -------------------
pwm = None
detection_triggered = False # 检测到人/救命标记
buzzer_active = False # 蜂鸣器运行标记
cap = None # 全局摄像头对象
face_cascade = None # 全局人脸分类器
profile_cascade = None # 全局侧脸分类器
# ------------------- 蜂鸣器控制 -------------------
def setup_buzzer():
global pwm
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(BUZZER_PIN, GPIO.OUT)
pwm = GPIO.PWM(BUZZER_PIN, FREQ_LOW)
def run_buzzer():
global buzzer_active, detection_triggered
buzzer_active = True
pwm.start(50)
start_time = time.time()
while (time.time() - start_time < BUZZER_DURATION) and buzzer_active and not detection_triggered:
pwm.ChangeFrequency(FREQ_LOW)
time.sleep(0.5)
pwm.ChangeFrequency(FREQ_HIGH)
time.sleep(0.5)
pwm.stop()
buzzer_active = False
# ------------------- PIR + 人脸检测 -------------------
def setup_pir():
GPIO.setup(PIR_PIN, GPIO.IN)
def setup_camera_and_cascades():
global cap, face_cascade, profile_cascade
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("错误:摄像头无法打开!")
return False
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
face_cascade = cv2.CascadeClassifier(FACE_CASCADE_PATH)
profile_cascade = cv2.CascadeClassifier(PROFILE_CASCADE_PATH)
if face_cascade.empty() or profile_cascade.empty():
print("错误:人脸分类器加载失败!")
return False
print("摄像头+分类器初始化完成")
return True
def detect_human():
global cap, face_cascade, profile_cascade
if not cap or not cap.isOpened():
return False
ret, img = cap.read()
if not ret:
return False
img = cv2.flip(img, 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=2, minSize=(30, 30))
profiles = profile_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=2, minSize=(30, 30))
if len(faces) > 0 or len(profiles) > 0:
print(f"检测到:正脸{len(faces)}个,侧脸{len(profiles)}个")
return len(faces) > 0 or len(profiles) > 0
def monitor_pir():
global detection_triggered, buzzer_active
print("PIR监控线程启动")
while buzzer_active and not detection_triggered:
current_val = GPIO.input(PIR_PIN)
if current_val == 1:
print("PIR检测到活动,持续人脸检测...")
if detect_human():
detection_triggered = True
print("1(检测到人体)")
break
time.sleep(0.5)
print("PIR监控线程退出")
# ------------------- Vosk 人声识别 -------------------
def setup_voice_recognition():
if not os.path.exists(VOSK_MODEL_PATH):
print("错误:Vosk模型目录不存在!")
return None, None, None
model = vosk.Model(VOSK_MODEL_PATH)
recognizer = vosk.KaldiRecognizer(model, 16000)
p = pyaudio.PyAudio()
stream = p.open(
format=pyaudio.paInt16,
channels=1,
rate=16000,
input=True,
frames_per_buffer=4000,
input_device_index=None
)
return recognizer, stream, p
def monitor_voice(recognizer, stream):
global detection_triggered, buzzer_active
while buzzer_active and not detection_triggered:
data = stream.read(4000, exception_on_overflow=False)
if recognizer.AcceptWaveform(data):
result = json.loads(recognizer.Result())
text = result.get("text", "").strip()
clean_text = text.replace(" ", "").replace("!", "").replace(",", "")
if "救命" in clean_text:
detection_triggered = True
print("1(人声识别到'救命')")
break
# ------------------- 资源释放 -------------------
def cleanup():
global buzzer_active, detection_triggered, cap
buzzer_active = False
detection_triggered = False
if cap and cap.isOpened():
cap.release()
print("摄像头已释放")
if pwm:
pwm.stop()
GPIO.cleanup()
cv2.destroyAllWindows()
if 'stream' in globals() and 'p_audio' in globals():
stream.stop_stream()
stream.close()
p_audio.terminate()
print("程序已停止,资源已释放")
# ------------------- GPS 功能 -------------------
def check_dialout_permission():
try:
groups = os.popen('groups').read().strip()
if 'dialout' in groups:
return True
else:
logging.warning("当前用户不在dialout组中,可能无法访问串口")
logging.warning("请运行: sudo usermod -aG dialout $USER,然后重新登录")
return False
except Exception as e:
logging.warning(f"检查权限时出错: {e}")
return False
class ATK1218GPS:
def __init__(self, port='/dev/ttyS0', baudrate=9600, timeout=2):
self.port = port
self.baudrate = baudrate
self.timeout = timeout
self.ser = None
self.db_conn = None
self.init_database()
logging.info(f"配置为使用 {self.port} 串口")
def connect(self):
try:
self.ser = serial.Serial(
self.port,
self.baudrate,
timeout=self.timeout,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
xonxoff=False,
rtscts=False
)
if self.ser.is_open:
logging.info(f"成功连接到GPS模块: {self.port}")
return True
else:
logging.error(f"无法打开 {self.port} 端口")
return False
except PermissionError:
logging.error(f"权限不足,无法访问 {self.port}")
logging.error("请确保用户已加入dialout组并重新登录")
return False
except Exception as e:
logging.error(f"连接GPS模块失败: {e}")
return False
def init_database(self):
try:
self.db_conn = sqlite3.connect("gps_data/location.db")
cursor = self.db_conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS locations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp DATETIME,
latitude REAL,
longitude REAL,
altitude REAL,
satellites INTEGER,
speed REAL,
course REAL,
fix_quality INTEGER
)
''')
cursor.execute("PRAGMA table_info(locations)")
columns = [column[1] for column in cursor.fetchall()]
if 'speed' not in columns:
cursor.execute("ALTER TABLE locations ADD COLUMN speed REAL")
logging.info("已添加speed列到数据库表")
if 'course' not in columns:
cursor.execute("ALTER TABLE locations ADD COLUMN course REAL")
logging.info("已添加course列到数据库表")
self.db_conn.commit()
logging.info("数据库初始化成功")
except Exception as e:
logging.error(f"数据库初始化失败: {e}")
def parse_nmea_sentence(self, sentence):
try:
if not sentence.startswith('$'):
return None
msg = pynmea2.parse(sentence)
if isinstance(msg, pynmea2.GGA):
data = {
'timestamp': datetime.datetime.now(),
'latitude': self.convert_to_decimal(msg.lat, msg.lat_dir),
'longitude': self.convert_to_decimal(msg.lon, msg.lon_dir),
'altitude': float(msg.altitude) if msg.altitude else None,
'satellites': int(msg.num_sats) if msg.num_sats else None,
'speed': None,
'course': None,
'fix_quality': int(msg.gps_qual) if msg.gps_qual else 0
}
return data
elif isinstance(msg, pynmea2.RMC):
data = {
'timestamp': datetime.datetime.now(),
'latitude': self.convert_to_decimal(msg.lat, msg.lat_dir),
'longitude': self.convert_to_decimal(msg.lon, msg.lon_dir),
'altitude': None,
'satellites': None,
'speed': float(msg.spd_over_grnd) if msg.spd_over_grnd else None,
'course': float(msg.true_course) if msg.true_course else None,
'fix_quality': 1 if msg.status == 'A' else 0
}
return data
return None
except pynmea2.ParseError:
return None
except Exception as e:
logging.warning(f"解析NMEA数据出错: {e}, 数据: {sentence}")
return None
def convert_to_decimal(self, value, direction):
if not value:
return None
try:
val = float(value)
degrees = int(val // 100)
minutes = val % 100
decimal_degrees = degrees + minutes / 60
if direction in ['S', 'W']:
decimal_degrees = -decimal_degrees
return round(decimal_degrees, 6)
except:
return None
def save_location(seimport os
import time
import threading
import RPi.GPIO as GPIO
import cv2
import numpy as np
import pyaudio
import vosk
import json
import serial
import pynmea2
import datetime
import sqlite3
from pathlib import Path
import logging
import sys
# ------------------- 硬件与模型配置 -------------------
BUZZER_PIN = 18 # BCM模式
FREQ_LOW = 1000
FREQ_HIGH = 2000
BUZZER_DURATION = 60 # 蜂鸣器持续秒数
PIR_PIN = 17 # BCM模式
FACE_CASCADE_PATH = '/home/pi/.local/lib/python3.7/site-packages/cv2/data/haarcascade_frontalface_alt2.xml'
PROFILE_CASCADE_PATH = '/home/pi/.local/lib/python3.7/site-packages/cv2/data/haarcascade_profileface.xml'
VOSK_MODEL_PATH = "/home/pi/vosk-model-small-cn-0.22"
# ------------------- 全局变量 -------------------
pwm = None
detection_triggered = False # 检测到人/救命标记
buzzer_active = False # 蜂鸣器运行标记
cap = None # 全局摄像头对象
face_cascade = None # 全局人脸分类器
profile_cascade = None # 全局侧脸分类器
# ------------------- 蜂鸣器控制 -------------------
def setup_buzzer():
global pwm
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(BUZZER_PIN, GPIO.OUT)
pwm = GPIO.PWM(BUZZER_PIN, FREQ_LOW)
def run_buzzer():
global buzzer_active, detection_triggered
buzzer_active = True
pwm.start(50)
start_time = time.time()
while (time.time() - start_time < BUZZER_DURATION) and buzzer_active and not detection_triggered:
pwm.ChangeFrequency(FREQ_LOW)
time.sleep(0.5)
pwm.ChangeFrequency(FREQ_HIGH)
time.sleep(0.5)
pwm.stop()
buzzer_active = False
# ------------------- PIR + 人脸检测 -------------------
def setup_pir():
GPIO.setup(PIR_PIN, GPIO.IN)
def setup_camera_and_cascades():
global cap, face_cascade, profile_cascade
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("错误:摄像头无法打开!")
return False
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 320)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)
face_cascade = cv2.CascadeClassifier(FACE_CASCADE_PATH)
profile_cascade = cv2.CascadeClassifier(PROFILE_CASCADE_PATH)
if face_cascade.empty() or profile_cascade.empty():
print("错误:人脸分类器加载失败!")
return False
print("摄像头+分类器初始化完成")
return True
def detect_human():
global cap, face_cascade, profile_cascade
if not cap or not cap.isOpened():
return False
ret, img = cap.read()
if not ret:
return False
img = cv2.flip(img, 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=2, minSize=(30, 30))
profiles = profile_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=2, minSize=(30, 30))
if len(faces) > 0 or len(profiles) > 0:
print(f"检测到:正脸{len(faces)}个,侧脸{len(profiles)}个")
return len(faces) > 0 or len(profiles) > 0
def monitor_pir():
global detection_triggered, buzzer_active
print("PIR监控线程启动")
while buzzer_active and not detection_triggered:
current_val = GPIO.input(PIR_PIN)
if current_val == 1:
print("PIR检测到活动,持续人脸检测...")
if detect_human():
detection_triggered = True
print("1(检测到人体)")
break
time.sleep(0.5)
print("PIR监控线程退出")
# ------------------- Vosk 人声识别 -------------------
def setup_voice_recognition():
if not os.path.exists(VOSK_MODEL_PATH):
print("错误:Vosk模型目录不存在!")
return None, None, None
model = vosk.Model(VOSK_MODEL_PATH)
recognizer = vosk.KaldiRecognizer(model, 16000)
p = pyaudio.PyAudio()
stream = p.open(
format=pyaudio.paInt16,
channels=1,
rate=16000,
input=True,
frames_per_buffer=4000,
input_device_index=None
)
return recognizer, stream, p
def monitor_voice(recognizer, stream):
global detection_triggered, buzzer_active
while buzzer_active and not detection_triggered:
data = stream.read(4000, exception_on_overflow=False)
if recognizer.AcceptWaveform(data):
result = json.loads(recognizer.Result())
text = result.get("text", "").strip()
clean_text = text.replace(" ", "").replace("!", "").replace(",", "")
if "救命" in clean_text:
detection_triggered = True
print("1(人声识别到'救命')")
break
# ------------------- 资源释放 -------------------
def cleanup():
global buzzer_active, detection_triggered, cap
buzzer_active = False
detection_triggered = False
if cap and cap.isOpened():
cap.release()
print("摄像头已释放")
if pwm:
pwm.stop()
GPIO.cleanup()
cv2.destroyAllWindows()
if 'stream' in globals() and 'p_audio' in globals():
stream.stop_stream()
stream.close()
p_audio.terminate()
print("程序已停止,资源已释放")
# ------------------- GPS 功能 -------------------
def check_dialout_permission():
try:
groups = os.popen('groups').read().strip()
if 'dialout' in groups:
return True
else:
logging.warning("当前用户不在dialout组中,可能无法访问串口")
logging.warning("请运行: sudo usermod -aG dialout $USER,然后重新登录")
return False
except Exception as e:
logging.warning(f"检查权限时出错: {e}")
return False
class ATK1218GPS:
def __init__(self, port='/dev/ttyS0', baudrate=9600, timeout=2):
self.port = port
self.baudrate = baudrate
self.timeout = timeout
self.ser = None
self.db_conn = None
self.init_database()
logging.info(f"配置为使用 {self.port} 串口")
def connect(self):
try:
self.ser = serial.Serial(
self.port,
self.baudrate,
timeout=self.timeout,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS,
xonxoff=False,
rtscts=False
)
if self.ser.is_open:
logging.info(f"成功连接到GPS模块: {self.port}")
return True
else:
logging.error(f"无法打开 {self.port} 端口")
return False
except PermissionError:
logging.error(f"权限不足,无法访问 {self.port}")
logging.error("请确保用户已加入dialout组并重新登录")
return False
except Exception as e:
logging.error(f"连接GPS模块失败: {e}")
return False
def init_database(self):
try:
self.db_conn = sqlite3.connect("gps_data/location.db")
cursor = self.db_conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS locations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp DATETIME,
latitude REAL,
longitude REAL,
altitude REAL,
satellites INTEGER,
speed REAL,
course REAL,
fix_quality INTEGER
)
''')
cursor.execute("PRAGMA table_info(locations)")
columns = [column[1] for column in cursor.fetchall()]
if 'speed' not in columns:
cursor.execute("ALTER TABLE locations ADD COLUMN speed REAL")
logging.info("已添加speed列到数据库表")
if 'course' not in columns:
cursor.execute("ALTER TABLE locations ADD COLUMN course REAL")
logging.info("已添加course列到数据库表")
self.db_conn.commit()
logging.info("数据库初始化成功")
except Exception as e:
logging.error(f"数据库初始化失败: {e}")
def parse_nmea_sentence(self, sentence):
try:
if not sentence.startswith('$'):
return None
msg = pynmea2.parse(sentence)
if isinstance(msg, pynmea2.GGA):
data = {
'timestamp': datetime.datetime.now(),
'latitude': self.convert_to_decimal(msg.lat, msg.lat_dir),
'longitude': self.convert_to_decimal(msg.lon, msg.lon_dir),
'altitude': float(msg.altitude) if msg.altitude else None,
'satellites': int(msg.num_sats) if msg.num_sats else None,
'speed': None,
'course': None,
'fix_quality': int(msg.gps_qual) if msg.gps_qual else 0
}
return data
elif isinstance(msg, pynmea2.RMC):
data = {
'timestamp': datetime.datetime.now(),
'latitude': self.convert_to_decimal(msg.lat, msg.lat_dir),
'longitude': self.convert_to_decimal(msg.lon, msg.lon_dir),
'altitude': None,
'satellites': None,
'speed': float(msg.spd_over_grnd) if msg.spd_over_grnd else None,
'course': float(msg.true_course) if msg.true_course else None,
'fix_quality': 1 if msg.status == 'A' else 0
}
return data
return None
except pynmea2.ParseError:
return None
except Exception as e:
logging.warning(f"解析NMEA数据出错: {e}, 数据: {sentence}")
return None
def convert_to_decimal(self, value, direction):
if not value:
return None
try:
val = float(value)
degrees = int(val // 100)
minutes = val % 100
decimal_degrees = degrees + minutes / 60
if direction in ['S', 'W']:
decimal_degrees = -decimal_degrees
return round(decimal_degrees, 6)
except:
return None
def save_location(self, location_data):
if not location_data or not self.db_conn:
return False
try:
cursor = self.db_conn.cursor()
cursor.execute('''
INSERT INTO locations (timestamp, latitude, longitude, altitude, satellites, speed, course, fix_quality)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
''', (
location_data['timestamp'],
location_data['latitude'],
location_data['longitude'],
location_data['altitude'],
location_data['satellites'],
location_data['speed'],
location_data['course'],
location_data['fix_quality']
))
self.db_conn.commit()
with open("gps_data/latest_location.txt", "w") as f:
f.write(f"时间: {location_data['timestamp']}\n")
f.write(f"纬度: {location_data['latitude']}\n")
f.write(f"经度: {location_data['longitude']}\n")
if location_data['altitude']:
f.write(f"海拔: {location_data['altitude']} 米\n")
if location_data['speed']:
f.write(f"速度: {location_data['speed']} 节\n")
f.write(f"航向: {location_data['course']} 度\n")
if location_data['satellites']:
f.write(f"卫星数量: {location_data['satellites']}\n")
f.write(f"定位质量: {location_data['fix_quality']}\n")
return True
except Exception as e:
logging.error(f"保存定位信息失败: {e}")
return False
def get_location(self, timeout=30):
"""获取有效位置信息,超时返回None"""
if not self.ser or not self.ser.is_open:
logging.warning("请先连接GPS模块")
return None
start_time = time.time()
logging.info("开始获取GPS定位...")
try:
while time.time() - start_time < timeout:
data = self.ser.readline().decode('utf-8', errors='ignore').strip()
if data:
location_data = self.parse_nmea_sentence(data)
if location_data and location_data.get('fix_quality', 0) > 0:
logging.info(f"成功获取定位: {location_data}")
self.save_location(location_data)
return location_data
time.sleep(0.1)
logging.warning("获取GPS定位超时")
return None
except Exception as e:
logging.error(f"获取定位数据出错: {e}")
return None
def close(self):
if self.ser and self.ser.is_open:
self.ser.close()
logging.info("已关闭GPS模块连接")
if self.db_conn:
self.db_conn.close()
logging.info("已关闭数据库连接")
# ------------------- LORA 功能 -------------------
class LoRaReceiver:
def __init__(self, port='/dev/ttyACM0', baudrate=9600, timeout=0.1):
self.port = port
self.baaudrate = baudrate
self.timeout = timeout
self.ser = None
self.running = False
def open(self):
try:
self.ser = serial.Serial(self.port, self.baudrate, timeout=self.timeout)
print(f"成功打开串口 {self.ser.name}")
self.running = True
return True
except Exception as e:
print(f"打开串口失败:{e}")
return False
def receive_data(self):
if not self.ser or not self.ser.is_open:
print("串口未打开,请先调用open()方法")
return None
if self.ser.in_waiting > 0:
try:
data = self.ser.read(self.ser.in_waiting).decode('utf-8', errors='ignore')
timestamp = time.strftime('%H:%M:%S')
return {
'timestamp': timestamp,
'data': data.strip()
}
except Exception as e:
print(f"接收数据错误:{e}")
return None
return None
def close(self):
if self.ser and self.ser.is_open:
self.ser.close()
self.running = False
print("串口已关闭")
def start_listening(self, callback=None):
if not self.open():
return
try:
print("开始监听LoRa数据... (按Ctrl+C停止)")
while self.running:
data = self.receive_data()
if data:
print(f"[{data['timestamp']}] 收到LoRa数据:{data['data']}")
if callback and callable(callback):
callback(data)
time.sleep(0.1)
except KeyboardInterrupt:
print("\n用户中断监听")
finally:
self.close()
class LoRaSender:
def __init__(self, port='/dev/ttyACM0', baud_rate=9600, timeout=1):
self.port = port
self.baud_rate = baud_rate
self.timeout = timeout
self.ser = None
def open(self):
try:
self.ser = serial.Serial(self.port, self.baud_rate, timeout=self.timeout)
print(f"成功打开串口 {self.ser.name}")
return True
except Exception as e:
print(f"打开串口失败:{e}")
return False
def send_message(self, message):
if not self.ser or not self.ser.is_open:
print("串口未打开,请先调用open()方法")
return False
if not message:
print("消息为空,不发送")
return False
try:
self.ser.write(message.encode('utf-8'))
print(f"✅ 已发送:{message}")
return True
except Exception as e:
print(f"发送失败:{e}")
return False
def close(self):
if self.ser and self.ser.is_open:
self.ser.close()
print("串口已关闭")
def send_and_close(self, message):
try:
if self.open():
self.send_message(message)
time.sleep(0.1)
finally:
self.close()
# ------------------- 主函数 -------------------
def main():
# 确保数据目录存在
data_dir = Path("gps_data")
data_dir.mkdir(exist_ok=True)
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler("gps_data/gps_log.log"),
logging.StreamHandler()
]
)
# 检查权限
if not check_dialout_permission():
logging.warning("串口访问权限可能存在问题")
# 初始化LoRa接收器
lora_receiver = LoRaReceiver(port='/dev/ttyACM0')
# 等待接收LoRa信号
print("等待接收LoRa信号...")
lora_receiver.open()
try:
while True:
data = lora_receiver.receive_data()
if data:
print(f"接收到LoRa信号: {data['data']}")
# 如果接收到信号,启动检测流程
start_detection()
# 检测完成后退出循环
break
time.sleep(1)
except KeyboardInterrupt:
print("\n用户中断程序")
finally:
lora_receiver.close()
cleanup()
def start_detection():
global detection_triggered, buzzer_active
# 初始化硬件
setup_buzzer()
setup_pir()
if not setup_camera_and_cascades():
cleanup()
return
recognizer, stream, p_audio = setup_voice_recognition()
if not recognizer or not stream or not p_audio:
cleanup()
return
# 启动状态
detection_triggered = False
buzzer_active = True
# 启动线程
buzzer_thread = threading.Thread(target=run_buzzer, daemon=True)
pir_thread = threading.Thread(target=monitor_pir, daemon=True)
voice_thread = threading.Thread(target=monitor_voice, args=(recognizer, stream), daemon=True)
buzzer_thread.start()
pir_thread.start()
voice_thread.start()
# 主线程等待
while buzzer_active and not detection_triggered:
time.sleep(1)
# 如果检测到人,获取GPS位置并通过LoRa发送
if detection_triggered:
# 获取GPS位置
gps = ATK1218GPS(port='/dev/ttyAMA0', baudrate=38400)
if gps.connect():
location_data = gps.get_location(timeout=30)
gps.close()
if location_data:
# 格式化位置信息
location_str = f"紧急位置: 纬度 {location_data['latitude']}, 经度 {location_data['longitude']}"
if location_data['altitude']:
location_str += f", 海拔 {location_data['altitude']}米"
# 通过LoRa发送位置信息
lora_sender = LoRaSender(port='/dev/ttyACM0')
lora_sender.send_and_close(location_str)
else:
logging.error("无法获取GPS定位信息")
else:
logging.error("无法连接GPS模块")
# 清理资源
cleanup()
if __name__ == '__main__':
try:
main()
except Exception as e:
logging.error(f"程序执行出错: {e}")
cleanup()
sys.exit(1)我把多个入口程序合并成一个主函数入口,按照我的逻辑来写主函数的代码,首先需要用接收函数读出接收到的信息,如果接收到了这个信息以后那么进行原来靠前的_main_块(直接启动就行,不需要再让用户输入1),如果检测到有人就进行GPS的定位,然后读取出GPS的信息以后在通过LORA模块发送函数,把这个信息发送出去。你看我发给你的代码能不能满足我的要求,有什么缺陷,可以订正了一个给我完整