revert 90b84b79569fbe40f67f86c0c61fcefdb4bcb83e
revert 上传文件至 红外2
This commit is contained in:
parent
90b84b7956
commit
bdaa3682b2
Binary file not shown.
@ -1,229 +0,0 @@
|
||||
{
|
||||
"metadata": {
|
||||
"create_time": "2025-05-14T16:29:46.405745",
|
||||
"total_commands": 24
|
||||
},
|
||||
"raw_data": {
|
||||
"power_on": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1807,
|
||||
"timestamp": "2025-05-14 16:26:50"
|
||||
},
|
||||
"power_off": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1805,
|
||||
"timestamp": "2025-05-14 16:26:54"
|
||||
},
|
||||
"cool_16": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1803,
|
||||
"timestamp": "2025-05-14 16:26:58"
|
||||
},
|
||||
"cool_17": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1805,
|
||||
"timestamp": "2025-05-14 16:27:02"
|
||||
},
|
||||
"cool_18": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1805,
|
||||
"timestamp": "2025-05-14 16:27:16"
|
||||
},
|
||||
"cool_19": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1809,
|
||||
"timestamp": "2025-05-14 16:27:23"
|
||||
},
|
||||
"cool_20": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1802,
|
||||
"timestamp": "2025-05-14 16:27:26"
|
||||
},
|
||||
"heat_16": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1801,
|
||||
"timestamp": "2025-05-14 16:27:31"
|
||||
},
|
||||
"heat_17": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1801,
|
||||
"timestamp": "2025-05-14 16:27:35"
|
||||
},
|
||||
"heat_18": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1803,
|
||||
"timestamp": "2025-05-14 16:27:40"
|
||||
},
|
||||
"heat_19": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1805,
|
||||
"timestamp": "2025-05-14 16:27:47"
|
||||
},
|
||||
"heat_20": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1801,
|
||||
"timestamp": "2025-05-14 16:27:51"
|
||||
},
|
||||
"mode_cool": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1804,
|
||||
"timestamp": "2025-05-14 16:28:09"
|
||||
},
|
||||
"mode_dry": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1811,
|
||||
"timestamp": "2025-05-14 16:28:13"
|
||||
},
|
||||
"mode_fan": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1809,
|
||||
"timestamp": "2025-05-14 16:28:18"
|
||||
},
|
||||
"up_down": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1811,
|
||||
"timestamp": "2025-05-14 16:28:29"
|
||||
},
|
||||
"left_right": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1807,
|
||||
"timestamp": "2025-05-14 16:28:37"
|
||||
},
|
||||
"fan_low": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1807,
|
||||
"timestamp": "2025-05-14 16:28:42"
|
||||
},
|
||||
"fan_mid": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1811,
|
||||
"timestamp": "2025-05-14 16:28:50"
|
||||
},
|
||||
"fan_high": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1809,
|
||||
"timestamp": "2025-05-14 16:28:56"
|
||||
},
|
||||
"turbo_on": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1808,
|
||||
"timestamp": "2025-05-14 16:29:01"
|
||||
},
|
||||
"turbo_off": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1809,
|
||||
"timestamp": "2025-05-14 16:29:25"
|
||||
},
|
||||
"sleep_on": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1804,
|
||||
"timestamp": "2025-05-14 16:29:30"
|
||||
},
|
||||
"sleep_off": {
|
||||
"raw": "PULSEDISTANCE",
|
||||
"protocol": 184,
|
||||
"bits": 1804,
|
||||
"timestamp": "2025-05-14 16:29:46"
|
||||
}
|
||||
},
|
||||
"analysis": {
|
||||
"protocols": {
|
||||
"184": {
|
||||
"sample_count": 24,
|
||||
"fixed_bits": [
|
||||
{
|
||||
"position": 0,
|
||||
"value": "P"
|
||||
},
|
||||
{
|
||||
"position": 1,
|
||||
"value": "U"
|
||||
},
|
||||
{
|
||||
"position": 2,
|
||||
"value": "L"
|
||||
},
|
||||
{
|
||||
"position": 3,
|
||||
"value": "S"
|
||||
},
|
||||
{
|
||||
"position": 4,
|
||||
"value": "E"
|
||||
},
|
||||
{
|
||||
"position": 5,
|
||||
"value": "D"
|
||||
},
|
||||
{
|
||||
"position": 6,
|
||||
"value": "I"
|
||||
},
|
||||
{
|
||||
"position": 7,
|
||||
"value": "S"
|
||||
},
|
||||
{
|
||||
"position": 8,
|
||||
"value": "T"
|
||||
},
|
||||
{
|
||||
"position": 9,
|
||||
"value": "A"
|
||||
},
|
||||
{
|
||||
"position": 10,
|
||||
"value": "N"
|
||||
},
|
||||
{
|
||||
"position": 11,
|
||||
"value": "C"
|
||||
},
|
||||
{
|
||||
"position": 12,
|
||||
"value": "E"
|
||||
}
|
||||
],
|
||||
"variable_bits": [],
|
||||
"template": [
|
||||
"P",
|
||||
"U",
|
||||
"L",
|
||||
"S",
|
||||
"E",
|
||||
"D",
|
||||
"I",
|
||||
"S",
|
||||
"T",
|
||||
"A",
|
||||
"N",
|
||||
"C",
|
||||
"E"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#include "irre.h"
|
||||
#include<Arduino.h>
|
||||
|
||||
#define CS_PIN 5
|
||||
#define IR_PIN 4
|
||||
|
||||
BinHeader configHeader;
|
||||
uint16_t rawData[200];
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
|
||||
if (!IRController::initializeSD(CS_PIN)) {
|
||||
Serial.println("SD卡初始化失败");
|
||||
while(1);
|
||||
}
|
||||
|
||||
if (!IRController::loadConfig("/ir_config.bin", &configHeader, rawData)) {
|
||||
Serial.println("配置文件加载失败");
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
IRController::sendIRSignal(rawData, configHeader.bits/16, IR_PIN);
|
||||
delay(5000);
|
||||
}
|
206
红外2/irre(1).py
206
红外2/irre(1).py
@ -1,206 +0,0 @@
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import struct
|
||||
from datetime import datetime
|
||||
|
||||
# 常量定义
|
||||
STEPS = [
|
||||
{"desc": "1. [基础] 按电源键开机", "cmd": "power_on"},
|
||||
{"desc": "2. [基础] 按电源键关机", "cmd": "power_off"},
|
||||
*[{"desc": f"3.{i+1} [制冷] 设置{i+16}℃", "cmd": f"cool_{i+16}"} for i in range(5)],#基础温度为16
|
||||
*[{"desc": f"4.{i+1} [制热] 设置{i+16}℃", "cmd": f"heat_{i+16}"} for i in range(5)],
|
||||
{"desc": "5.1 [模式] 制冷模式", "cmd": "mode_cool"},
|
||||
{"desc": "5.2 [模式] 除湿模式", "cmd": "mode_dry"},
|
||||
{"desc": "5.3 [模式] 送风模式", "cmd": "mode_fan"},
|
||||
{"desc": "5.4 [模式] 上下风", "cmd": "up_down"},#上下风
|
||||
{"desc": "6.1 [风速] 左右风", "cmd": "left_right"},#左右风
|
||||
{"desc": "6.2 [风速] 低速", "cmd": "fan_low"},
|
||||
{"desc": "6.3 [风速] 中速", "cmd": "fan_mid"},
|
||||
{"desc": "6.4 [风速] 高速", "cmd": "fan_high"},
|
||||
{"desc": "7.1 [特殊] 超强风速", "cmd": "turbo_on"},#超强风速
|
||||
{"desc": "7.2 [特殊] 静音风速", "cmd": "turbo_off"},#静音风速
|
||||
{"desc": "7.5 [特殊] 睡眠模式开", "cmd": "sleep_on"},
|
||||
{"desc": "7.6 [特殊] 睡眠模式关", "cmd": "sleep_off"},
|
||||
|
||||
|
||||
|
||||
|
||||
]
|
||||
|
||||
def validate_signal(data):
|
||||
"""增强版信号验证"""
|
||||
pattern = r"""
|
||||
uint16_t\s+rawData\[(\d+)\]\s*=\s* # 匹配数组声明
|
||||
{([\d,\s]+)};?[\s\S]*? # 捕获数组内容
|
||||
Protocol\s*=\s*(\w+) # 协议类型
|
||||
(?:.*?(\d+)\s+bits)? # 可选位数匹配
|
||||
"""
|
||||
match = re.search(pattern, data, re.VERBOSE | re.IGNORECASE)
|
||||
|
||||
if not match:
|
||||
return False, None, None, None
|
||||
|
||||
try:
|
||||
arr_length = int(match.group(1))
|
||||
raw_data = list(map(int, match.group(2).split(',')))
|
||||
protocol = match.group(3).upper()
|
||||
bits = int(match.group(4)) if match.group(4) else len(raw_data)*16
|
||||
|
||||
# 数据长度校验
|
||||
if len(raw_data) != arr_length:
|
||||
print(f"数据长度不匹配: 声明{arr_length} 实际{len(raw_data)}")
|
||||
return False, None, None, None
|
||||
|
||||
return raw_data, protocol, bits, len(data)
|
||||
except Exception as e:
|
||||
print(f"解析错误: {str(e)}")
|
||||
return False, None, None, None
|
||||
|
||||
def analyze_signals(collected_data):
|
||||
"""执行控制变量分析"""
|
||||
analysis = {"protocols": {}}
|
||||
|
||||
# 按协议分组
|
||||
protocol_groups = {}
|
||||
for cmd, data in collected_data.items():
|
||||
proto = data['protocol']
|
||||
protocol_groups.setdefault(proto, []).append(data)
|
||||
|
||||
# 分析每个协议
|
||||
for proto, group in protocol_groups.items():
|
||||
proto_analysis = {
|
||||
"sample_count": len(group),
|
||||
"fixed_bits": [],
|
||||
"variable_bits": [],
|
||||
"template": []
|
||||
}
|
||||
|
||||
# 位级分析
|
||||
max_length = max(len(d["raw"]) for d in group)
|
||||
bit_analysis = [[] for _ in range(max_length)]
|
||||
|
||||
for data in group:
|
||||
for i, val in enumerate(data["raw"]):
|
||||
bit_analysis[i].append(val)
|
||||
|
||||
# 识别固定/可变位
|
||||
for idx, values in enumerate(bit_analysis):
|
||||
unique_vals = set(values)
|
||||
if len(unique_vals) == 1:
|
||||
proto_analysis["fixed_bits"].append({
|
||||
"position": idx,
|
||||
"value": values[0]
|
||||
})
|
||||
else:
|
||||
proto_analysis["variable_bits"].append({
|
||||
"position": idx,
|
||||
"values": list(unique_vals)
|
||||
})
|
||||
|
||||
# 生成协议模板
|
||||
proto_analysis["template"] = [
|
||||
"V" if any(idx == b["position"] for b in proto_analysis["variable_bits"])
|
||||
else group[0]["raw"][idx]
|
||||
for idx in range(len(group[0]["raw"]))
|
||||
]
|
||||
|
||||
analysis["protocols"][proto] = proto_analysis
|
||||
|
||||
return analysis
|
||||
|
||||
def collect_signals():
|
||||
"""主采集流程"""
|
||||
collected = {}
|
||||
print("\n空调红外信号采集系统启动")
|
||||
|
||||
for step_num, step in enumerate(STEPS, 1):
|
||||
while True:
|
||||
print(f"\n[{step_num}/{len(STEPS)}] {step['desc']}")
|
||||
print("请输入红外信号数据(输入'exit'退出):")
|
||||
data = input().strip()
|
||||
|
||||
if data.lower() == 'exit':
|
||||
if input("确认退出?(y/n): ").lower() == 'y':
|
||||
save_data(collected)
|
||||
return
|
||||
|
||||
valid, raw, proto, bits = validate_signal(data)
|
||||
if valid:
|
||||
collected[step['cmd']] = {
|
||||
"raw": raw,
|
||||
"protocol": proto,
|
||||
"bits": bits,
|
||||
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
}
|
||||
print(f"√ 已记录:{step['cmd']}")
|
||||
break
|
||||
print("× 格式错误!需包含:\n1.完整C数组 2.协议信息 3.正确数据格式")
|
||||
|
||||
analysis = analyze_signals(collected)
|
||||
save_data(collected, analysis)
|
||||
print(f"\n采集完成!有效数据:{len(collected)}条")
|
||||
|
||||
def convert_to_bin(json_path):
|
||||
"""将JSON配置转换为二进制格式"""
|
||||
with open(json_path, 'r') as f:
|
||||
config = json.load(f)
|
||||
|
||||
bin_data = bytearray()
|
||||
for cmd in config['raw_data'].values():
|
||||
# 协议类型(4字节) + 位数(4字节) + 时间戳(12字节)
|
||||
bin_data.extend(struct.pack('<I', cmd['protocol']))
|
||||
bin_data.extend(struct.pack('<I', cmd['bits']))
|
||||
|
||||
# 时间编码调整(年-2000压缩到1字节,其他字段范围校验)
|
||||
dt = datetime.strptime(cmd['timestamp'], "%Y-%m-%d %H:%M:%S")
|
||||
year_byte = dt.year - 2000
|
||||
if not (0 <= year_byte <= 255):
|
||||
year_byte = max(0, min(year_byte, 255))
|
||||
time_bytes = struct.pack('<6B',
|
||||
year_byte,
|
||||
max(1, min(dt.month, 12)),
|
||||
max(1, min(dt.day, 31)),
|
||||
dt.hour,
|
||||
dt.minute,
|
||||
dt.second
|
||||
)
|
||||
bin_data.extend(time_bytes)
|
||||
|
||||
bin_path = os.path.splitext(json_path)[0] + '.bin'
|
||||
with open(bin_path, 'wb') as f:
|
||||
f.write(bin_data)
|
||||
print(f"二进制配置已生成: {os.path.basename(bin_path)}")
|
||||
|
||||
|
||||
def save_data(data, analysis=None):
|
||||
"""保存数据到文件"""
|
||||
config = {
|
||||
"metadata": {
|
||||
"create_time": datetime.now().isoformat(),
|
||||
"total_commands": len(data)
|
||||
},
|
||||
"raw_data": data,
|
||||
"analysis": analysis if analysis else {}
|
||||
}
|
||||
|
||||
file_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "ir_config.json")
|
||||
with open(file_path, "w") as f:
|
||||
json.dump(config, f, indent=2)
|
||||
print("配置已保存至 ir_config.json")
|
||||
convert_to_bin(file_path)
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("="*40)
|
||||
print("红外信号采集分析系统 v2.0")
|
||||
print("操作说明:")
|
||||
print("1. 保持设备连接")
|
||||
print("2. 按提示操作遥控器")
|
||||
print("3. 从串口监视器复制数据")
|
||||
print("="*40)
|
||||
|
||||
try:
|
||||
collect_signals()
|
||||
except KeyboardInterrupt:
|
||||
print("\n操作中断!正在保存数据...")
|
||||
save_data(collected if 'collected' in locals() else {})
|
51
红外2/irre.h
51
红外2/irre.h
@ -1,51 +0,0 @@
|
||||
#ifndef IRRE_H
|
||||
#define IRRE_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SD.h>
|
||||
#include <IRremote.h>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
uint32_t protocol;
|
||||
uint32_t bits;
|
||||
struct {
|
||||
uint8_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
uint8_t hour;
|
||||
uint8_t minute;
|
||||
uint8_t second;
|
||||
} timestamp;
|
||||
} BinHeader;
|
||||
#pragma pack(pop)
|
||||
|
||||
class IRController {
|
||||
public:
|
||||
static bool initializeSD(uint8_t csPin = 5);
|
||||
static bool loadConfig(const char* path, BinHeader* header, uint16_t* rawData);
|
||||
static void sendIRSignal(uint16_t* rawData, size_t length, uint8_t irPin = 4);
|
||||
};
|
||||
|
||||
bool IRController::initializeSD(uint8_t csPin) {
|
||||
if(!SD.begin(csPin)) return false;
|
||||
return SD.exists("/ir_config.bin");
|
||||
}
|
||||
|
||||
bool IRController::loadConfig(const char* path, BinHeader* header, uint16_t* rawData) {
|
||||
File file = SD.open(path);
|
||||
if(!file) return false;
|
||||
|
||||
file.read((byte*)header, sizeof(BinHeader));
|
||||
size_t dataSize = (header->bits + 15) / 16 * 2;
|
||||
file.read((byte*)rawData, dataSize);
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void IRController::sendIRSignal(uint16_t* rawData, size_t length, uint8_t irPin) {
|
||||
IrSender.sendRaw(rawData, length, 38, false);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user