#!/usr/bin/env python3
"""
简化的船端接收器 - 适合实际部署

使用微控制器（Arduino/ESP32）+ 简单的音频检测
不需要复杂的电脑和录音
"""

import time
from dataclasses import dataclass
from typing import List, Tuple


@dataclass
class MorseCommand:
    """摩斯指令"""
    command_type: str  # NAVIGATE, STOP, SPEED, etc.
    parameters: dict
    confidence: float


class SimpleBoatReceiver:
    """
    简化的船接收器

    硬件需求：
    1. 微控制器 (Arduino/ESP32)
    2. 音频检测模块 (LM393)
    3. 对讲机
    4. GPS模块
    5. 电机控制

    不需要：
    ✗ 船载电脑
    ✗ 音频接口
    ✗ 复杂的录音
    """

    def __init__(self):
        """初始化接收器"""
        self.last_command = None
        self.current_position = {"lat": 0, "lon": 0}
        self.target_position = {"lat": 0, "lon": 0}
        self.current_speed = 0.0
        self.motor_speed = 0

    def receive_from_walkietalkie(self):
        """
        从对讲机接收信号

        硬件连接：
        对讲机音频输出 → LM393音频检测模块 → 单片机数字引脚

        工作原理：
        1. 对讲机播放摩斯音频
        2. LM393检测声音
        3. 有声音时输出HIGH，静音时输出LOW
        4. 单片机测量脉冲宽度
        5. 短脉冲=点，长脉冲=划
        """

        print("\n📡 等待对讲机信号...")
        print("硬件连接:")
        print("  对讲机SPK → LM393 IN")
        print("  LM393 OUT → Arduino D2")
        print("  Arduino GND → LM393 GND")

        # 模拟接收信号（实际硬件会自动检测）
        signals = self.detect_morse_signals()

        if signals:
            command = self.decode_signals_to_command(signals)
            return command

        return None

    def detect_morse_signals(self) -> List[str]:
        """
        检测摩斯信号

        Arduino代码示例：
        ```arduino
        int audioPin = 2;  // LM393输出引脚
        int lastState = LOW;
        unsigned long pulseStart = 0;
        String morseCode = "";

        void loop() {
          int state = digitalRead(audioPin);

          if (state != lastState) {
            if (state == HIGH) {
              // 声音开始
              pulseStart = millis();
            } else {
              // 声音结束
              unsigned long duration = millis() - pulseStart;

              if (duration < 200) {
                morseCode += "・";  // 点
              } else if (duration < 600) {
                morseCode += "-";   // 划
              }
            }
            lastState = state;
          }

          // 超时检测（字符间间隔）
          // 处理接收到的摩斯码
        }
        ```

        Returns:
            摩斯信号列表 ["・", "-", "-", "・", "・", "・"]
        """

        # 模拟检测结果
        # 实际硬件会自动返回真实信号
        print("  检测到信号...")
        return ["・", "-", "-", "・", "・", "・", " ", "・", "・", "・", "・"]

    def decode_signals_to_command(self, signals: List[str]) -> MorseCommand:
        """
        将信号解码为指令

        Args:
            signals: 摩斯信号列表

        Returns:
            指令对象
        """
        # 转换为摩斯字符串
        morse_str = "".join(signals)

        print(f"  接收摩斯: {morse_str}")

        # 简化的命令映射
        commands = {
            "・--・": "STOP",      # 停止
            "-・--": "RETURN",     # 返航
            "・-": "YES",         # 是
            "-・": "NO",          # 否
            "・・・---・・・": "SOS",  # 求救
        }

        # 检查是否是预定义命令
        for morse, cmd in commands.items():
            if morse in morse_str:
                print(f"  ✓ 识别命令: {cmd}")
                return MorseCommand(
                    command_type=cmd,
                    parameters={},
                    confidence=1.0
                )

        # 如果不是预定义命令，尝试解析坐标
        # NAV 30.61 114.32 的摩斯形式
        if "NAV " in morse_str or morse_str.startswith("・-・ "):  # NAV的摩斯
            # 这里需要更复杂的解析
            # 简化处理：返回NAVIGATE命令
            return MorseCommand(
                command_type="NAVIGATE",
                parameters={
                    "lat": 30.6100,
                    "lon": 114.3200,
                    "speed": 5.0
                },
                confidence=0.9
            )

        return MorseCommand(
            command_type="UNKNOWN",
            parameters={},
            confidence=0.0
        )

    def execute_command(self, command: MorseCommand):
        """
        执行指令

        Args:
            command: 指令对象
        """
        print(f"\n⚙️  执行指令: {command.command_type}")

        if command.command_type == "STOP":
            self.stop_motors()

        elif command.command_type == "NAVIGATE":
            lat = command.parameters.get('lat', 0)
            lon = command.parameters.get('lon', 0)
            speed = command.parameters.get('speed', 5.0)
            self.navigate_to(lat, lon, speed)

        elif command.command_type == "RETURN":
            self.return_to_home()

        elif command.command_type == "SOS":
            self.emergency_stop()

        else:
            print(f"  ⚠️  未知命令: {command.command_type}")

    def navigate_to(self, lat: float, lon: float, speed: float):
        """导航到指定位置"""
        print(f"  导航到: {lat:.4f}, {lon:.4f}")
        print(f"  速度: {speed}节")

        # 设置目标位置
        self.target_position = {"lat": lat, "lon": lon}
        self.current_speed = speed

        # 控制电机
        self.set_motor_speed(int(speed * 10))

    def stop_motors(self):
        """停止电机"""
        print("  ✓ 电机停止")
        self.motor_speed = 0
        self.current_speed = 0
        # Arduino: analogWrite(motorPin, 0)

    def set_motor_speed(self, speed: int):
        """设置电机速度"""
        print(f"  ✓ 电机速度: {speed}")
        self.motor_speed = speed

        # Arduino代码示例：
        # analogWrite(motorPin, speed)

    def return_to_home(self):
        """返航"""
        print("  返航模式")
        home_lat = 30.5928  # 武汉
        home_lon = 114.3055
        self.navigate_to(home_lat, home_lon, 5.0)

    def emergency_stop(self):
        """紧急停止"""
        print("  🚨 紧急停止！")
        self.stop_motors()

    def send_status_back(self):
        """
        发送状态回岸端

        方法1: 发送固定摩斯音频
        方法2: 使用对讲机CTCSS
        方法3: 定时发送心跳
        """
        # 生成状态消息
        status = f"POS {self.current_position['lat']:.2f} {self.current_position['lon']:.2f}"

        # 转换为摩斯并播放
        # 这需要一个简单的摩斯发送器
        print(f"\n📤 发送状态: {status}")

        # 简化的状态发送：
        # 使用蜂鸣器或LED发送摩斯
        # 对讲机麦克风接收


class UltrasonicBoatReceiver:
    """
    超简化船接收器（最简单方案）

    完全不需要电脑，只需要：
    1. 对讲机
    2. 几个简单的电路
    3. 预设的响应模式
    """

    def __init__(self):
        """初始化超简化接收器"""
        self.presets = {
            "3短音": "前进",
            "2短音": "左转",
            "1短音": "右转",
            "长音": "停止",
        }

    def simple_audio_detection(self):
        """
        超简单音频检测

        硬件：
        对讲机 → 扬声器 → 驻极体麦克风 → 比较器 → Arduino

        不需要：
        ✗ 电脑
        ✗ 音频接口
        ✗ 复杂解码

        只需要：
        ✓ 检测声音次数
        ✓ 检测声音长度
        ✓ 执行预设动作
        """

        print("\n📡 超简单检测模式")
        print("只需要检测：")
        print("  - 声音次数")
        print("  - 声音长短")
        print("  - 执行预设动作")

        # 预设模式
        print("\n预设模式：")
        for pattern, action in self.presets.items():
            print(f"  {pattern}: {action}")

        # 示例：检测到3短音 → 前进
        detected_pattern = "3短音"
        action = self.presets.get(detected_pattern, "未知")

        print(f"\n检测到: {detected_pattern}")
        print(f"执行: {action}")

        return action


def show_hardware_connections():
    """显示硬件连接图"""
    print("""
╔══════════════════════════════════════════════════════════╗
║           船端硬件连接 - 简化方案                         ║
╚══════════════════════════════════════════════════════════╝

方案1: 单片机 + 音频检测（推荐）

┌─────────────┐
│  对讲机B    │
│  (USV船上)  │
└──────┬──────┘
       │ 音频输出
       │ (SPK接口)
       ↓
┌─────────────┐
│  LM393      │
│  音频检测   │
│  模块       │
└──────┬──────┘
       │ 数字输出
       │ (HIGH/LOW)
       ↓
┌─────────────┐
│  Arduino    │
│  微控制器   │
│             │
│  读取引脚   │
│  测量脉冲   │
│  识别摩斯   │
│  执行指令   │
└──────┬──────┘
       │ 控制信号
       ↓
┌─────────────┐
│  电机驱动   │
│  L298N      │
└──────┬──────┘
       │
       ↓
┌─────────────┐
│  船用电机   │
│  (推进器)   │
└─────────────┘

配件:
- 对讲机: $50
- LM393模块: $2
- Arduino Nano: $10
- 电机驱动: $5
- 电机: $20
- 电池: $15
- 其他: $10

总计: 约$112

优点:
✅ 便宜
✅ 轻便
✅ 省电
✅ 可靠
✅ 防水容易


方案2: ESP32 + WiFi（现代化）

┌─────────────┐
│  对讲机B    │
└──────┬──────┘
       │
       ↓
┌─────────────┐
│  ESP32      │
│  (带WiFi)   │
│             │
│  接收音频   │
│  解码摩斯   │
│  执行指令   │
│  WiFi回传   │
└──────┬──────┘
       │ WiFi
       ↓
┌─────────────┐
│  手机/电脑  │
│  (监控)     │
└─────────────┘

配件:
- ESP32: $8
- 对讲机: $50
- 电机: $20
- 其他: $15

总计: 约$93

优点:
✅ 更便宜
✅ WiFi监控
✅ 可编程
✅ 低功耗


方案3: 超简化（纯硬件）

┌─────────────┐
│  对讲机B    │
└──────┬──────┘
       │
       ↓
┌─────────────┐
│  555定时器  │
│  电路       │
└──────┬──────┘
       │
       ↓
┌─────────────┐
│  继电器     │
│  控制       │
└──────┬──────┘
       │
       ↓
┌─────────────┐
│  电机       │
└─────────────┘

优点:
✅ 最简单
✅ 最便宜
✅ 最可靠
缺点:
✗ 只能预设动作
✗ 无反馈

    """)


def show_arduino_code():
    """显示Arduino代码"""
    print("""
╔══════════════════════════════════════════════════════════╗
║           Arduino代码示例                                ║
╚══════════════════════════════════════════════════════════╝

// 引脚定义
const int audioPin = 2;     // LM393输出
const int motorPin = 9;     // 电机PWM
const int ledPin = 13;      // 状态LED

// 变量
int lastState = LOW;
unsigned long pulseStart = 0;
String morseCode = "";
unsigned long lastSignalTime = 0;

void setup() {
  Serial.begin(9600);
  pinMode(audioPin, INPUT);
  pinMode(motorPin, OUTPUT);
  pinMode(ledPin, OUTPUT);

  Serial.println("USV Boat Receiver Ready");
}

void loop() {
  int state = digitalRead(audioPin);

  // 检测边沿变化
  if (state != lastState) {
    if (state == HIGH) {
      // 声音开始
      pulseStart = millis();
      digitalWrite(ledPin, HIGH);
    } else {
      // 声音结束
      unsigned long duration = millis() - pulseStart;

      // 判断点或划
      if (duration > 50 && duration < 200) {
        morseCode += "・";  // 点
        Serial.print("・");
      } else if (duration >= 200 && duration < 600) {
        morseCode += "-";   // 划
        Serial.print("-");
      }

      lastSignalTime = millis();
    }
    lastState = state;
  }

  // 检测字符间隔（500ms静音）
  if (millis() - lastSignalTime > 500 && morseCode.length() > 0) {
    Serial.print(" ");
    processMorse(morseCode);
    morseCode = "";
  }

  // 检测单词间隔（1500ms静音）
  if (millis() - lastSignalTime > 1500 && morseCode.length() > 0) {
    Serial.println();
    morseCode = "";
  }
}

void processMorse(String morse) {
  Serial.print("收到: ");
  Serial.println(morse);

  // 简单命令解析
  if (morse == "・・・---・・・") {
    executeCommand("SOS");
  } else if (morse == "・--・") {
    executeCommand("STOP");
  } else if (morse == "-・--") {
    executeCommand("RETURN");
  } else if (morse == "・-・-・") {
    executeCommand("FORWARD");
  } else if (morse == "-・--・") {
    executeCommand("BACKWARD");
  }
}

void executeCommand(String cmd) {
  Serial.print("执行: ");
  Serial.println(cmd);

  if (cmd == "SOS") {
    emergencyStop();
  } else if (cmd == "STOP") {
    stopMotor();
  } else if (cmd == "RETURN") {
    returnHome();
  } else if (cmd == "FORWARD") {
    setMotor(150);  // 前进
  } else if (cmd == "BACKWARD") {
    setMotor(-150); // 后退
  }
}

void setMotor(int speed) {
  // 限制范围
  if (speed > 255) speed = 255;
  if (speed < -255) speed = -255;

  if (speed >= 0) {
    analogWrite(motorPin, speed);
  } else {
    analogWrite(motorPin, -speed);
  }

  Serial.print("电机速度: ");
  Serial.println(speed);
}

void stopMotor() {
  analogWrite(motorPin, 0);
  Serial.println("电机停止");
}

void emergencyStop() {
  stopMotor();
  // 发送紧急信号
  for (int i = 0; i < 3; i++) {
    digitalWrite(ledPin, HIGH);
    delay(100);
    digitalWrite(ledPin, LOW);
    delay(100);
  }
}

void returnHome() {
  Serial.println("返航模式");
  setMotor(100);  // 慢速返航
  // 这里应该添加GPS导航逻辑
}
    """)


def main():
    """主程序"""
    print("""
╔══════════════════════════════════════════════════════════╗
║     简化的船端接收器 - 实用方案                         ║
║                                                          ║
║  不需要复杂的电脑，只需要单片机！                        ║
╚══════════════════════════════════════════════════════════╝
    """)

    print("\n选择:")
    print("  1. 查看硬件连接")
    print("  2. 查看Arduino代码")
    print("  3. 运行演示")
    print("  4. 退出")

    choice = input("\n选择 (1-4): ").strip()

    if choice == "1":
        show_hardware_connections()

    elif choice == "2":
        show_arduino_code()

    elif choice == "3":
        print("\n运行简化接收器演示...")

        # 方案1: 简化接收器
        receiver = SimpleBoatReceiver()

        # 模拟接收指令
        command = receiver.receive_from_walkietalkie()

        if command:
            receiver.execute_command(command)

        # 方案2: 超简化接收器
        print("\n" + "="*60)
        simple = UltrasonicBoatReceiver()
        action = simple.simple_audio_detection()

    elif choice == "4":
        print("\n👋 再见！")

    else:
        print("✗ 无效选择")


if __name__ == "__main__":
    main()
