上传文件至 /

This commit is contained in:
孙瑶 2025-12-03 16:13:38 +08:00
parent eab09e5498
commit 705ff60827
5 changed files with 674 additions and 0 deletions

131
SensorDetector.py Normal file
View File

@ -0,0 +1,131 @@
import serial
import serial.tools.list_ports
import time
import datetime
import struct
import threading
import json
class SensorDetector:
def __init__(self, log_path, sensor_configs):
"""
初始化方法支持多传感器配置
:param log_path: 日志路径
:param sensor_configs: 传感器配置列表格式如[{"port": "COM6", "id": "X11223366S_1"}, {"port": "COM7", "id": "X11223366S_2"}]
"""
self.log_path = log_path
self.sensor_configs = sensor_configs # 新增:多传感器配置
self.serials = {} # 新增:存储多个串口连接
self.data3 = []
self.latest_data = {} # 新增:存储每个传感器的最新数据
self.running = True # 新增:轮询控制标志
# 确保日志目录存在
import os
if not os.path.exists(self.log_path):
os.makedirs(self.log_path)
def _open_serial_port(self, port, baudrate=38400, timeout=1):
"""修改:支持指定端口打开串口"""
try:
ser = serial.Serial(port=port, baudrate=baudrate, timeout=timeout)
if ser.isOpen():
print(f"Successfully open serial port {port}")
return ser
else:
print(f"Failure to open serial port {port}")
return None
except Exception as e:
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(f"{self.log_path}/Exception_log.txt", "a") as f:
f.write(f"{now} open serial port {port} error:{e}\n")
return None
def _send_command(self, ser, data):
"""修改:接受串口对象作为参数"""
try:
send_data = struct.pack("%dB" % (len(data)), *data)
ser.write(send_data)
except Exception as e:
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(f"{self.log_path}/Exception_log.txt", "a") as f:
f.write(f"{now} send command error:{e}\n")
def _sensor_worker(self, sensor_id, port, callback):
"""新增:单个传感器的工作线程"""
ser = self._open_serial_port(port)
if not ser:
return
self.serials[sensor_id] = ser
# 发送启动指令
self._send_command(ser, [0x8A])
current_second_data = []
last_second = time.time()
while self.running:
try:
count0 = ser.inWaiting()
current_time = time.time()
if count0 > 0:
read_buffer = ser.read(88)
if len(read_buffer) == 88 and read_buffer[0] == 0xff: # 增加长度校验,修复索引错误
sensor_data = {
'sensor_id': sensor_id, # 新增标记传感器ID
'heart_rate': read_buffer[65],
'blood_oxygen': read_buffer[66],
'micro_circulation': read_buffer[67],
'fatigue_index': read_buffer[68],
'systolic_pressure': read_buffer[71],
'diastolic_pressure': read_buffer[72],
'cardiac_output': read_buffer[73]
}
current_second_data.append(sensor_data)
# 每秒回调一次数据
if current_time - last_second >= 1:
callback(current_second_data)
current_second_data = []
last_second = current_time
time.sleep(0.01) # 降低CPU占用
except Exception as e:
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(f"{self.log_path}/Exception_log.txt", "a") as f:
f.write(f"{now} sensor {sensor_id} data reading error:{e}\n")
time.sleep(1)
def detect_sensors(self, callback):
"""修改:启动多传感器轮询线程"""
try:
ports = list(serial.tools.list_ports.comports())
for p in ports:
print(p)
# 为每个传感器启动工作线程
threads = []
for config in self.sensor_configs:
t = threading.Thread(
target=self._sensor_worker,
args=(config["id"], config["port"], callback),
daemon=True
)
threads.append(t)
t.start()
# 保持主线程运行
while self.running:
time.sleep(1)
except Exception as e:
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(f"{self.log_path}/Exception_log.txt", "a") as f:
f.write(f"{now} overall sensor detection error:{e}\n")
def stop(self):
"""新增:停止所有传感器线程"""
self.running = False
for ser in self.serials.values():
if ser and ser.isOpen():
ser.close()

44
kk_mian.py Normal file
View File

@ -0,0 +1,44 @@
import serial
import serial.tools.list_ports
import time
import datetime
import struct
import threading
import paho.mqtt.client as mqtt
import json
from SensorDetector import SensorDetector
import sys
sys.path.append('../../net')
from mqtt_proxy import MQTTPublisher
# MQTT配置
MQTT_BROKER = "60.204.151.68"
MQTT_PORT = 1883
mqtt_topic = "senser_MKS_data"
mqtt_publisher = MQTTPublisher(MQTT_BROKER, MQTT_PORT, mqtt_topic)
mqtt_publisher.connect()
def handle_sensor_data(data_list):
"""处理所有传感器的每秒数据"""
global mqtt_publisher
for data in data_list:
print("handle_sensor_data:", data)
if data["heart_rate"] == 0:
continue
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print("发布成功,mqtt消息")
mqtt_publisher.publish(json_str)
if __name__ == "__main__":
log_path = "./log_pip6/"
sensor_configs = [
{"port": "COM6", "id": "X11223366S_1"},
{"port": "COM7", "id": "X11223366S_2"}
]
detector = SensorDetector(log_path, sensor_configs)
try:
detector.detect_sensors(handle_sensor_data)
except KeyboardInterrupt:
print("用户中断,停止传感器检测")
detector.stop()

156
kk_mysql_save_api.py Normal file
View File

@ -0,0 +1,156 @@
import requests
import json
import time
from datetime import datetime
def save_mysql_data(sensor_id,json_data,save_path):
url = "http://47.106.222.181:25081/algorithm/oxygen/result/data_post"
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
payload = json.dumps({
"sensor_id": "X12345679S",
"raw_file_path": save_path
})
print("payload:",payload)
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
print(response.json())
def save_mysql_data_with_jpg(device_id,module_code,json_data,save_path,save_jpg_path):
url = "http://47.106.222.181:25081/algorithm/oxygen/result/data_post"
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
payload = json.dumps({
"device_id": "d100000002",
# "device_id": "d100000002", #机器人ID
"module_code": module_code, #传感器ID
"timestamp": current_time,
"confidence": 0.99,
#传感器输出结果
"result_data":json_data,
# "result_data": {
# "detection": "fall",
# "position": {
# "x": 125,
# "y": 80,
# "width": 50,
# "height": 120
# },
# "duration": 3.5
# },
#需要替换
# "raw_ref": "/storage/raw/20250814/DEV-001/camera_001.mp4"
"raw_ref": save_path,
"pic_ref":save_jpg_path
})
print("payload:",payload)
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
print(response.json())
def save_senser_mysql_data(device_id, module_code, json_data, save_path):
# def save_senser_mysql_data():
url = "http://47.106.222.181:25081/elderly/health/data"
current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
payload = json.dumps({
"elderly_id": 1, # 必选关联老人ID
"sensor_id": "X12345679S", # 必选传感器设备ID
"module_code": module_code, # 可选,算法模块编码
# "sensor_data_path": "http://47.106.222.181:25079/sftp-images/uploads/device_info/data/device_info/d80801000058/senser_001/20250826/20250826_09/20250826_09_33_01_d80801000058_senser_001.json", # 可选,传感器原始数据存储路径
"sensor_data_path": save_path, # 可选,传感器原始数据存储路径
"algorithm_data_path": "/processed/202508/oxygen_1005_1030.json", # 可选,算法处理数据存储路径
"data_time": current_time # 可选,数据采集时间,默认当前时间
})
print("payload:", payload)
headers = {
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
print(response.json())
def test_main():
start_time = time.time() # 获取开始时间
save_path = "/d100000002/X12345681S/20251101/20251101_11/20251101_11_11_11_d100000002_X12345681S.json"
json_data = {'heart_rate': 0, 'blood_oxygen': 0, 'micro_circulation': 0, 'fatigue_index': 0, 'systolic_pressure': 0, 'diastolic_pressure': 0, 'cardiac_output': 0}
save_mysql_data("X11223366S",json_data,save_path)
end_time = time.time() # 获取结束时间
# 计算耗时
duration = end_time - start_time
print(f"Function 'save_mysql_data' took {duration} seconds to execute.")
#0.668 秒
def test_main_jpg():
start_time = time.time() # 获取开始时间
json_data = {
"detection": "fall",
"position": {
"x": 125,
"y": 80,
"width": 50,
"height": 120
},
"duration": 3.5
}
save_path = "/storage/raw/20250814/DEV-001/camera_001.mp4"
save_jpg_path = "/storage/raw/20250814/DEV-001/camera_001.jpg"
save_mysql_data_with_jpg("d80801000062", "A0001", json_data, save_path, save_jpg_path)
end_time = time.time() # 获取结束时间
# 计算耗时
duration = end_time - start_time
print(f"Function 'save_mysql_data' took {duration} seconds to execute.")
#0.668 秒
def test_main_1():
start_time = time.time() # 获取开始时间
json_data = {
"detection": "fall",
"position": {
"x": 125,
"y": 80,
"width": 50,
"height": 120
},
"duration": 3.5
}
save_path = "/storage/raw/20250814/DEV-001/camera_001.mp4"
save_senser_mysql_data( "d100000002","A0001",json_data,save_path)
end_time = time.time() # 获取结束时间
# 计算耗时
duration = end_time - start_time
print(f"Function 'save_mysql_data' took {duration} seconds to execute.")
#0.668 秒
if __name__ == "__main__":
test_main()
# test_main_jpg()
# save_senser_mysql_data()

90
kk_sftp_save_api.py Normal file
View File

@ -0,0 +1,90 @@
import paramiko
import os
import posixpath
def mkdir_p(sftp, remote_dir):
"""递归创建远程目录(类似 mkdir -p"""
if remote_dir == '/':
return # 根目录假设已存在
try:
sftp.stat(remote_dir)
return
except FileNotFoundError:
pass
parent_dir = posixpath.dirname(remote_dir)
if parent_dir != '/':
mkdir_p(sftp, parent_dir)
try:
sftp.mkdir(remote_dir)
except Exception as e:
raise RuntimeError(f"创建目录失败: {remote_dir}, 错误: {str(e)}")
def sftp_upload(host, port, username, password, local_path, remote_path,file_name):
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(host, port, username, password)
# 创建SFTP会话
sftp = ssh.open_sftp()
result = False
return_path = ""
try:
mkdir_p(sftp, remote_path)
# 上传文件
target_path = remote_path+"/"+file_name
sftp.put(local_path, target_path)
print(f"文件上传成功: {local_path} -> {target_path}")
result = True
return_path = target_path
finally:
# 关闭SFTP会话和SSH连接
sftp.close()
ssh.close()
return result,return_path
def sftp_upload_one_file(local_path,mkdir_remote_path,file_name):
HOSTNAME = '47.106.222.181'
PORT = 25078 # 默认SSH端口是22
USERNAME = 'user'
PASSWORD = 'password'
# local_path = '/home/cat/shuikeWorkSpace/vscode_code/2025_workspace/shuike_dev/3rdparty/rk3576_NDK/app/node/save_data_app/Snipaste_2025-07-22_16-28-55.jpg' # 本地文件路径
# remote_path = '/files/
remote_base_path = "/files/uploads/device_info" #文件系统的鹿鸣
remote_path = remote_base_path+"/"+ mkdir_remote_path # 远程文件路径
print("remote_path1:",remote_path)
flag,remote_path = sftp_upload(HOSTNAME, PORT, USERNAME, PASSWORD, local_path, remote_path,file_name)
if flag:
print("上传成功")
#远程路径
print("remote_path2:",remote_path)
remote_path_without_prefix = remote_path.replace("/files/", "") # /uploads/device_info
get_url = "http://47.106.222.181:25079/sftp-images/" + remote_path_without_prefix
# http://47.106.222.181:25079/sftp-images/uploads/device_info
print("get_url:",get_url)
return get_url
if __name__ == "__main__":
# 使用示例
#本地图片
# local_path = '/home/cat/shuikeWorkSpace/vscode_code/2025_WorkSpace/snapshot_1.jpg' # 本地文件路径
local_path = r'D:/ntxm/sensor_data/snapshot_1.jpg'
#远程路径
mkdir_remote_path = "d80801000058/sensor/20250814/20250814_01" #本地存储路径
#图片链接
file_name = 'Snipaste_2025-07-22_16-28-55.jpg' # 远程文件路径
#进行上传
down_url = sftp_upload_one_file(local_path,mkdir_remote_path,file_name)

253
kk_tfcard_save_api.py Normal file
View File

@ -0,0 +1,253 @@
import os
import json
import random
from datetime import datetime
import time
from PIL import Image, ImageDraw
import numpy as np
import cv2
#pip install Pillow 2_28
#python -m pip install Pillow -i https://mirrors.aliyun.com/pypi/simple/
#python -m pip install spdlog -i https://mirrors.aliyun.com/pypi/simple/
# python -m pip install paramiko -i https://mirrors.aliyun.com/pypi/simple/
class save_data_manager:
def __init__(self,base_path,robot_id):
self.base_path_ = base_path # TF卡挂载点
self.robot_id_ = robot_id
#数据库对象
def save_data_to_tfcard_json(self,json_data,dir_name,json_type):
"""生成并保存数据到TF卡"""
now = datetime.now()
date_str = now.strftime("%Y%m%d")
hour_str = now.strftime("%H")
# 1. 创建目录
save_dir = os.path.join(self.base_path_, "data", "device_info", self.robot_id_, dir_name, date_str, f"{date_str}_{hour_str}")
os.makedirs(save_dir, exist_ok=True)
# 2. 创建文件
timestamp = None
if json_data['timestamp']:
timestamp = json_data['timestamp']
else:
timestamp = datetime.now().strftime("%Y%m%d_%H_%M_%S")
filename = f"{timestamp}_{self.robot_id_}_{json_type}.json"
# 3. 写入json
json_save_path = os.path.join(save_dir, filename)
print("json_path:",json_save_path)
with open(json_save_path, "w") as f:
json.dump(json_data, f, indent=2)
print(f"Saved face data: {filename}")
return json_save_path
def save_data_to_tfcard_jpg(self,frame_data,dir_name,jpg_type):
"""生成并保存数据到TF卡"""
now = datetime.now()
date_str = now.strftime("%Y%m%d")
hour_str = now.strftime("%H")
# 1. 创建目录
save_dir = os.path.join(self.base_path_, "data", "device_info", self.robot_id_, dir_name, date_str, f"{date_str}_{hour_str}")
os.makedirs(save_dir, exist_ok=True)
# 2. 创建文件
timestamp = datetime.now().strftime("%Y%m%d_%H_%M_%S")
filename = f"{timestamp}_{self.robot_id_}_{jpg_type}.jpg"
# 3. 写入jpg
jpg_save_path = os.path.join(save_dir, filename)
print("jpg_save_path:",jpg_save_path)
cv2.imwrite(jpg_save_path,frame_data)
return jpg_save_path
"""生成模拟人脸关键点数据"""
def generate_fake_face_data(self):
"""生成模拟人脸关键点数据"""
return {
"timestamp": datetime.now().strftime("%Y%m%d_%H_%M_%S"),
"robot_id": self.robot_id_,
"results": [
{"x": round(random.uniform(0, 200),0), "y": round(random.uniform(0, 1),0)} for _ in range(68)
],
"confidence": random.uniform(0.7, 0.99)
}
"""生成模拟人体姿态数据"""
def generate_fake_pose_data(self):
"""生成模拟人体姿态数据"""
keypoints = ["nose", "left_eye", "right_eye", "left_ear", "right_ear",
"left_shoulder", "right_shoulder", "left_elbow", "right_elbow",
"left_wrist", "right_wrist", "left_hip", "right_hip",
"left_knee", "right_knee", "left_ankle", "right_ankle"]
return {
"timestamp": datetime.now().strftime("%Y%m%d_%H_%M_%S"),
"robot_id": self.robot_id_,
"results": {kp: {
"x": round(random.uniform(0, 200),0),
"y": round(random.uniform(0, 200),0),
"score": round(random.uniform(0.7, 0.99),2)
} for kp in keypoints}
}
"""生成模拟-血样-传感器数据"""
def generate_fake_sensor_001_data(self):
print("生成模拟-血样-传感器数据")
mks_data_random = {
'heart_rate': random.randint(60, 100), # 假设 心率 在60到180之间
'blood_oxygen': random.randint(85, 100), # 假设 血氧 在85到100之间
'micro_circulation': random.randint(50, 100), # 假设 微循环值 在50到100之间
'fatigue_index': random.randint(0, 100), # 假设 疲劳 指数在0到100之间
'systolic_pressure': random.randint(90, 180), # 假设 收缩压 在90到180之间
'diastolic_pressure': random.randint(60, 120), # 假设 舒张压 在60到120之间
'cardiac_output': random.randint(40, 100) # 假设 心输出 在40到100之间
}
print("mks_data_random:",mks_data_random)
return {
"timestamp": datetime.now().strftime("%Y%m%d_%H_%M_%S"),
"robot_id": self.robot_id_,
"result": mks_data_random,
}
def generate_sensor_001_data(self,mks_data_random):
print("生成模拟-血样-传感器数据")
# mks_data_random = {
# 'heart_rate': random.randint(60, 100), # 假设 心率 在60到180之间
# 'blood_oxygen': random.randint(85, 100), # 假设 血氧 在85到100之间
# 'micro_circulation': random.randint(50, 100), # 假设 微循环值 在50到100之间
# 'fatigue_index': random.randint(0, 100), # 假设 疲劳 指数在0到100之间
# 'systolic_pressure': random.randint(90, 180), # 假设 收缩压 在90到180之间
# 'diastolic_pressure': random.randint(60, 120), # 假设 舒张压 在60到120之间
# 'cardiac_output': random.randint(40, 100) # 假设 心输出 在40到100之间
# }
print("mks_data_random:",mks_data_random)
return {
"timestamp": datetime.now().strftime("%Y%m%d_%H_%M_%S"),
"robot_id": self.robot_id_,
"result": mks_data_random,
}
"""生成模拟-毫米波-传感器数据"""
def generate_fake_sensor_002_data(self):
print("生成模拟-毫米波-传感器数据")
sensor_data = {
"Part1Rst": {
"Battery": 100,
"Status": ["01"],
"CountNum": random.randint(1, 4),
"IsFall": 0
},
"Part2Rst": {
"TargetNum": 1,
"Target0": {
"ID": 16,
"PtNum": 22,
"PointCloud": [
[-0.0691750283216743, 0.13160428640200078, 1.3956739328119288],
[-0.07847705523541838, 0.15392815246426594, 1.383871249877477],
[-0.08118316058836383, 0.15254387167066272, 1.3841153359302658],
[-0.08118316058836383, 0.15254387167066272, 1.3841153359302658],
[-0.0929625, 0.17252076850321676, 1.3695799337803236],
[-0.08985277963433623, 0.1735465559405953, 1.366252506565061],
[-0.08981986049799257, 0.1729446846963683, 1.3632120794907499],
[-0.09402106608514023, 0.2008075149795186, 1.3752118342759272],
[-0.16259914164055408, 0.3659265315697133, 1.2686130237385964],
[-0.16217132883698243, 0.36379021511710175, 1.2623032883896637],
[-0.16910310730617623, 0.3631439575505753, 1.2691036666139888],
[-0.1638440883521219, 0.3831408593633806, 1.2404052475851655],
[-0.17067092536679368, 0.3803548338347067, 1.2408964990548133],
[-0.17067092536679368, 0.3803548338347067, 1.2408964990548133],
[-0.17294653770501756, 0.4044264626613462, 1.2315388724510081],
[-0.17294653770501756, 0.4044264626613462, 1.2315388724510081],
[-0.17235096722025173, 0.40169857121649716, 1.224546809430924],
[-0.16789502279593474, 0.4368924567706128, 1.236433858829858],
[-0.16789502279593474, 0.4368924567706128, 1.236433858829858],
[-0.16789502279593474, 0.4368924567706128, 1.236433858829858],
[-0.16719017622805205, 0.5141370904782002, 1.2188803542752917],
[-0.16758717901763867, 0.5169416889917281, 1.227432168376347]
],
"CenterPoint": [-0.12395, 0.34706, 1.27605]
}
},
"Part3Rst": {
"TargetNum": 1,
"Target0": {
"ID": 16,
"Point": [-0.12395, 0.32227, 1.2512599999999998],
"HeartRate": random.randint(50, 65),
"BreathRate": 4
}
}
}
print("sensor_data:",sensor_data)
return {
"timestamp": datetime.now().strftime("%Y%m%d_%H_%M_%S"),
"robot_id": self.robot_id_,
"result": sensor_data,
}
"""生成模拟图片"""
def generate_fake_image(self,width=640, height=480):
"""生成模拟图片"""
img = Image.new("RGB", (width, height), color=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
draw = ImageDraw.Draw(img)
# 添加一些随机形状
for _ in range(random.randint(3, 10)):
x1 = random.randint(0, width)
y1 = random.randint(0, height)
x2 = random.randint(x1, width)
y2 = random.randint(y1, height)
draw.rectangle([x1, y1, x2, y2],
fill=(random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
# 将 PIL 图像转换为 NumPy 数组
numpy_image = np.array(img)
return numpy_image
if __name__ == "__main__":
base_path = "./sftp-data_1" # TF卡挂载点
robot_id = "d80801000058"
#json写入管理(完成)
test = save_data_manager(base_path,robot_id)
#数据插入管理
#数据库同步管理(完成)
#生成人脸数据
# face_data = test.generate_fake_face_data()
# test.save_data_to_tfcard_json(face_data,dir_name="face",json_type="face")
# #TODO 插入数据库
# #人体人脸数据
# pose_data = test.generate_fake_pose_data()
# test.save_data_to_tfcard_json(pose_data,dir_name="pose",json_type="pose")
# #TODO 插入数据库
#传感器数据
sensor_data = test.generate_fake_sensor_001_data()
test.save_data_to_tfcard_json(sensor_data,dir_name="sensor_001",json_type="sensor_001")
sensor_data = test.generate_fake_sensor_002_data()
test.save_data_to_tfcard_json(sensor_data,dir_name="sensor_002",json_type="sensor_002")
#TODO 插入数据
# frame_data = test.generate_fake_image()
# test.save_data_to_tfcard_jpg(frame_data,dir_name="face_jpg",jpg_type="jpg")
#TODO 插入数据库