上位机(Upper Computer)基础入门及其C与C++实例

上位机(Upper Computer)基础入门及其C与C++实例

1. 上位机基础概念

1.1 什么是上位机

上位机(Upper Computer)是指在主从式计算机系统中,用于监控、控制、数据采集、分析与处理的主控计算机。它通常负责人机交互界面、数据存储、高级算法运算以及下位机控制。

在工业控制系统、智能设备、实验室仪器、物联网设备等场景中,上位机担任关键角色,负责协调系统整体运行,并提供用户友好的操作界面。

1.2 上位机的主要功能

  1. 人机交互:提供图形用户界面(GUI),使操作人员能够方便地监控系统状态及发送控制命令
  2. 数据采集:从下位机或传感器网络获取数据
  3. 数据显示:以图表、仪表盘、趋势图等形式可视化展示数据
  4. 数据存储:将采集的数据保存到数据库或文件系统
  5. 远程控制:向下位机发送控制命令和参数
  6. 数据分析:对采集的数据进行处理、分析、计算,提取有价值的信息
  7. 报警管理:检测异常情况并提示操作人员
  8. 系统配置:提供接口设置系统参数

1.3 上位机开发方式分类

  1. 专用软件开发:使用C/C++、C#、Java等编程语言自主开发完整的上位机软件
  2. 开发环境集成:使用LabVIEW、MATLAB、Python等集成开发环境快速搭建
  3. 工业软件二次开发:基于SCADA、组态软件等工业控制软件进行二次开发
  4. Web应用开发:开发基于浏览器的上位机系统,便于远程访问和跨平台使用

1.4 通信接口与协议

上位机与下位机之间的通信是系统正常运行的关键,常见接口和协议包括:

  1. 硬件接口

    • 串口(RS-232/RS-485/RS-422)
    • USB
    • 以太网
    • CAN总线
    • 无线通信(Wi-Fi/蓝牙/ZigBee等)
  2. 通信协议

    • Modbus
    • PROFINET
    • OPC UA
    • MQTT
    • 自定义协议

2. C语言上位机开发基础

2.1 串口通信基础示例

c

/**
 * serial_port_example.c - 串口通信示例
 * 演示如何使用C语言实现基本的串口通信功能
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
    #include <fcntl.h>
    #include <termios.h>
    #include <errno.h>
#endif

// 平台无关的串口处理结构体
typedef struct {
    #ifdef _WIN32
        HANDLE handle;
    #else
        int fd;
    #endif
    char port_name[64];
    int baud_rate;
} SerialPort;

// 打开串口
int serialport_open(SerialPort* port) {
    #ifdef _WIN32
        // Windows 平台
        char port_path[64];
        sprintf(port_path, "\\\\.\\%s", port->port_name); // 例如:\\.\COM1
        
        port->handle = CreateFile(port_path,
                                  GENERIC_READ | GENERIC_WRITE,
                                  0,
                                  NULL,
                                  OPEN_EXISTING,
                                  0,
                                  NULL);
        
        if (port->handle == INVALID_HANDLE_VALUE) {
            printf("Error opening serial port: %s\n", port->port_name);
            return -1;
        }
        
        // 设置串口参数
        DCB dcb = {0};
        dcb.DCBlength = sizeof(DCB);
        
        if (!GetCommState(port->handle, &dcb)) {
            printf("Error getting comm state\n");
            CloseHandle(port->handle);
            return -1;
        }
        
        // 设置波特率
        dcb.BaudRate = port->baud_rate;
        dcb.ByteSize = 8;                // 8位数据位
        dcb.StopBits = ONESTOPBIT;       // 1个停止位
        dcb.Parity = NOPARITY;           // 无校验
        
        if (!SetCommState(port->handle, &dcb)) {
            printf("Error setting comm state\n");
            CloseHandle(port->handle);
            return -1;
        }
        
        // 设置超时
        COMMTIMEOUTS timeouts = {0};
        timeouts.ReadIntervalTimeout = 50;
        timeouts.ReadTotalTimeoutConstant = 50;
        timeouts.ReadTotalTimeoutMultiplier = 10;
        timeouts.WriteTotalTimeoutConstant = 50;
        timeouts.WriteTotalTimeoutMultiplier = 10;
        
        if (!SetCommTimeouts(port->handle, &timeouts)) {
            printf("Error setting timeouts\n");
            CloseHandle(port->handle);
            return -1;
        }
    #else
        // Linux/Unix 平台
        port->fd = open(port->port_name, O_RDWR | O_NOCTTY | O_NDELAY);
        
        if (port->fd < 0) {
            printf("Error opening serial port: %s\n", port->port_name);
            return -1;
        }
        
        // 设置串口参数
        struct termios options;
        tcgetattr(port->fd, &options);
        
        // 设置波特率
        speed_t baud;
        switch (port->baud_rate) {
            case 9600:   baud = B9600;   break;
            case 19200:  baud = B19200;  break;
            case 38400:  baud = B38400;  break;
            case 57600:  baud = B57600;  break;
            case 115200: baud = B115200; break;
            default:     baud = B9600;   break;
        }
        
        cfsetispeed(&options, baud);
        cfsetospeed(&options, baud);
        
        options.c_cflag |= (CLOCAL | CREAD);   // 启用接收器并忽略调制解调器控制线
        options.c_cflag &= ~PARENB;            // 无校验
        options.c_cflag &= ~CSTOPB;            // 1个停止位
        options.c_cflag &= ~CSIZE;             // 掩码字符大小位
        options.c_cflag |= CS8;                // 8位数据位
        options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 原始输入
        options.c_iflag &= ~(IXON | IXOFF | IXANY); // 禁用软件流控
        options.c_oflag &= ~OPOST;            // 原始输出
        
        // 设置超时
        options.c_cc[VMIN] = 0;               // 非阻塞读取
        options.c_cc[VTIME] = 10;             // 100ms超时
        
        tcsetattr(port->fd, TCSANOW, &options);
    #endif
    
    return 0;
}

// 关闭串口
void serialport_close(SerialPort* port) {
    #ifdef _WIN32
        if (port->handle != INVALID_HANDLE_VALUE) {
            CloseHandle(port->handle);
            port->handle = INVALID_HANDLE_VALUE;
        }
    #else
        if (port->fd >= 0) {
            close(port->fd);
            port->fd = -1;
        }
    #endif
}

// 发送数据
int serialport_write(SerialPort* port, const void* buffer, size_t size) {
    #ifdef _WIN32
        DWORD bytes_written = 0;
        if (!WriteFile(port->handle, buffer, size, &bytes_written, NULL)) {
            printf("Error writing to serial port\n");
            return -1;
        }
        return bytes_written;
    #else
        return write(port->fd, buffer, size);
    #endif
}

// 接收数据
int serialport_read(SerialPort* port, void* buffer, size_t size) {
    #ifdef _WIN32
        DWORD bytes_read = 0;
        if (!ReadFile(port->handle, buffer, size, &bytes_read, NULL)) {
            printf("Error reading from serial port\n");
            return -1;
        }
        return bytes_read;
    #else
        return read(port->fd, buffer, size);
    #endif
}

// 主程序
int main(int argc, char* argv[]) {
    SerialPort port;
    
    // 默认参数
    #ifdef _WIN32
        strcpy(port.port_name, "COM1");
    #else
        strcpy(port.port_name, "/dev/ttyUSB0");
    #endif
    port.baud_rate = 9600;
    
    // 处理命令行参数
    if (argc > 1) {
        strncpy(port.port_name, argv[1], sizeof(port.port_name)-1);
    }
    if (argc > 2) {
        port.baud_rate = atoi(argv[2]);
    }
    
    printf("Opening %s at %d baud\n", port.port_name, port.baud_rate);
    
    // 打开串口
    if (serialport_open(&port) < 0) {
        printf("Failed to open serial port\n");
        return -1;
    }
    
    printf("Serial port opened successfully\n");
    
    // 发送测试数据
    const char* test_message = "Hello from upper computer\r\n";
    int bytes_written = serialport_write(&port, test_message, strlen(test_message));
    printf("Sent %d bytes: %s\n", bytes_written, test_message);
    
    // 接收数据
    char buffer[128];
    printf("Waiting for data...\n");
    
    // 简单的循环接收和显示数据
    int loop_count = 0;
    while (loop_count < 10) {  // 执行10次读取操作
        memset(buffer, 0, sizeof(buffer));
        int bytes_read = serialport_read(&port, buffer, sizeof(buffer) - 1);
        
        if (bytes_read > 0) {
            printf("Received %d bytes: %s\n", bytes_read, buffer);
        } else if (bytes_read < 0) {
            printf("Error reading from serial port\n");
            break;
        }
        
        // 简单的等待
        #ifdef _WIN32
            Sleep(500);  // 500毫秒
        #else
            usleep(500000);  // 500000微秒 = 500毫秒
        #endif
        
        loop_count++;
    }
    
    // 关闭串口
    serialport_close(&port);
    printf("Serial port closed\n");
    
    return 0;
}

2.2 简单文件数据记录器

c

/**
 * data_logger.c - 简单的数据记录器
 * 演示如何使用C语言开发数据采集和记录功能
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#ifdef _WIN32
    #include <windows.h>
    #define sleep_ms(ms) Sleep(ms)
#else
    #include <unistd.h>
    #define sleep_ms(ms) usleep((ms) * 1000)
#endif

// 数据记录结构
typedef struct {
    FILE* file;
    char filename[128];
    int is_open;
    int record_count;
    time_t start_time;
} DataLogger;

// 传感器数据结构
typedef struct {
    float temperature;
    float humidity;
    float pressure;
    float voltage;
    time_t timestamp;
} SensorData;

// 初始化数据记录器
int logger_init(DataLogger* logger, const char* prefix) {
    time_t now;
    struct tm* timeinfo;
    char timestamp[64];
    
    // 获取当前时间
    time(&now);
    timeinfo = localtime(&now);
    strftime(timestamp, sizeof(timestamp), "%Y%m%d_%H%M%S", timeinfo);
    
    // 创建文件名: prefix_YYYYMMDD_HHMMSS.csv
    snprintf(logger->filename, sizeof(logger->filename), 
             "%s_%s.csv", prefix, timestamp);
    
    // 打开文件
    logger->file = fopen(logger->filename, "w");
    if (!logger->file) {
        printf("Error: Unable to open file %s\n", logger->filename);
        return -1;
    }
    
    // 写入CSV头
    fprintf(logger->file, "Timestamp,DateTime,Temperature,Humidity,Pressure,Voltage\n");
    fflush(logger->file);
    
    logger->is_open = 1;
    logger->record_count = 0;
    logger->start_time = now;
    
    printf("Data logger initialized. Recording to %s\n", logger->filename);
    return 0;
}

// 记录数据
int logger_record(DataLogger* logger, const SensorData* data) {
    char datetime[64];
    struct tm* timeinfo;
    
    if (!logger->is_open || !logger->file) {
        printf("Error: Logger not initialized\n");
        return -1;
    }
    
    // 格式化时间
    timeinfo = localtime(&data->timestamp);
    strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", timeinfo);
    
    // 写入数据记录
    fprintf(logger->file, "%ld,%s,%.2f,%.2f,%.2f,%.2f\n",
            data->timestamp,
            datetime,
            data->temperature,
            data->humidity,
            data->pressure,
            data->voltage);
    
    // 确保及时写入到文件
    fflush(logger->file);
    
    logger->record_count++;
    return 0;
}

// 关闭数据记录器
void logger_close(DataLogger* logger) {
    time_t now;
    double elapsed_seconds;
    
    if (logger->is_open && logger->file) {
        time(&now);
        elapsed_seconds = difftime(now, logger->start_time);
        
        printf("Data logger closed. Recorded %d samples in %.1f seconds (%.2f samples/sec)\n",
               logger->record_count, elapsed_seconds, 
               logger->record_count / (elapsed_seconds > 0 ? elapsed_seconds : 1));
        
        fclose(logger->file);
        logger->file = NULL;
        logger->is_open = 0;
    }
}

// 模拟传感器数据采集
void simulate_sensor_reading(SensorData* data) {
    static float temp_base = 25.0;
    static float humid_base = 50.0;
    static float pressure_base = 1013.0;
    static float voltage_base = 12.0;
    
    // 生成带有一些随机变化的模拟数据
    data->temperature = temp_base + ((float)rand() / RAND_MAX * 2.0f - 1.0f);
    data->humidity = humid_base + ((float)rand() / RAND_MAX * 5.0f - 2.5f);
    data->pressure = pressure_base + ((float)rand() / RAND_MAX * 3.0f - 1.5f);
    data->voltage = voltage_base + ((float)rand() / RAND_MAX * 0.4f - 0.2f);
    
    // 添加缓慢的变化趋势
    temp_base += ((float)rand() / RAND_MAX * 0.1f - 0.05f);
    humid_base += ((float)rand() / RAND_MAX * 0.2f - 0.1f);
    
    // 设置当前时间戳
    time(&data->timestamp);
}

// 显示传感器数据
void display_sensor_data(const SensorData* data) {
    char datetime[64];
    struct tm* timeinfo;
    
    // 格式化时间
    timeinfo = localtime(&data->timestamp);
    strftime(datetime, sizeof(datetime), "%Y-%m-%d %H:%M:%S", timeinfo);
    
    printf("\rTime: %s | Temp: %.2f°C | Humidity: %.2f%% | Pressure: %.2f hPa | Voltage: %.2f V",
           datetime, data->temperature, data->humidity, data->pressure, data->voltage);
    fflush(stdout);
}

int main(int argc, char* argv[]) {
    DataLogger logger;
    SensorData sensor_data;
    int sample_rate_ms = 1000;  // 默认每秒采样一次
    int max_samples = 60;       // 默认采集60个样本
    int i;
    
    // 处理命令行参数
    if (argc > 1) {
        sample_rate_ms = atoi(argv[1]);
        if (sample_rate_ms < 100) sample_rate_ms = 100;  // 最小100毫秒
    }
    if (argc > 2) {
        max_samples = atoi(argv[2]);
        if (max_samples < 1) max_samples = 1;
    }
    
    printf("Data Logger Example\n");
    printf("Sample rate: %d ms, Max samples: %d\n", sample_rate_ms, max_samples);
    
    // 初始化随机数生成器
    srand((unsigned int)time(NULL));
    
    // 初始化数据记录器
    if (logger_init(&logger, "sensor_data") < 0) {
        return -1;
    }
    
    printf("Starting data collection...\n");
    
    // 采集并记录数据
    for (i = 0; i < max_samples && logger.is_open; i++) {
        // 模拟传感器读数
        simulate_sensor_reading(&sensor_data);
        
        // 显示数据
        display_sensor_data(&sensor_data);
        
        // 记录数据
        logger_record(&logger, &sensor_data);
        
        // 等待到下一个采样时间
        sleep_ms(sample_rate_ms);
    }
    
    printf("\nData collection completed.\n");
    
    // 关闭数据记录器
    logger_close(&logger);
    
    return 0;
}

2.3 简单命令行解析器

c

/**
 * command_parser.c - 简单的命令行解析器
 * 演示如何实现命令行接口来控制设备
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_CMD_LEN 256
#define MAX_ARGS 16

// 命令处理函数原型
typedef int (*CommandFunc)(int argc, char* argv[]);

// 命令结构
typedef struct {
    const char* name;
    const char* help;
    CommandFunc func;
} Command;

// 系统状态
typedef struct {
    int is_connected;
    int device_status;
    float temperature;
    float setpoint;
    int output_power;
} SystemState;

// 全局系统状态
SystemState system_state = {
    .is_connected = 0,
    .device_status = 0,
    .temperature = 25.0f,
    .setpoint = 22.0f,
    .output_power = 0
};

// 命令: help
int cmd_help(int argc, char* argv[]);

// 命令: connect
int cmd_connect(int argc, char* argv[]) {
    if (system_state.is_connected) {
        printf("Already connected\n");
        return 0;
    }
    
    if (argc < 2) {
        printf("Usage: connect <device>\n");
        return -1;
    }
    
    printf("Connecting to %s...\n", argv[1]);
    
    // 这里只是模拟连接
    system_state.is_connected = 1;
    system_state.device_status = 1;
    
    printf("Connected successfully\n");
    return 0;
}

// 命令: disconnect
int cmd_disconnect(int argc, char* argv[]) {
    if (!system_state.is_connected) {
        printf("Not connected\n");
        return 0;
    }
    
    printf("Disconnecting...\n");
    
    // 模拟断开连接
    system_state.is_connected = 0;
    system_state.device_status = 0;
    
    printf("Disconnected\n");
    return 0;
}

// 命令: status
int cmd_status(int argc, char* argv[]) {
    printf("System Status:\n");
    printf("  Connection: %s\n", system_state.is_connected ? "Connected" : "Disconnected");
    
    if (system_state.is_connected) {
        printf("  Device Status: %s\n", system_state.device_status ? "ON" : "OFF");
        printf("  Temperature: %.1f°C\n", system_state.temperature);
        printf("  Setpoint: %.1f°C\n", system_state.setpoint);
        printf("  Output Power: %d%%\n", system_state.output_power);
    }
    
    return 0;
}

// 命令: set
int cmd_set(int argc, char* argv[]) {
    if (!system_state.is_connected) {
        printf("Error: Not connected\n");
        return -1;
    }
    
    if (argc < 3) {
        printf("Usage: set <parameter> <value>\n");
        printf("Parameters: setpoint, power\n");
        return -1;
    }
    
    if (strcmp(argv[1], "setpoint") == 0) {
        float setpoint = atof(argv[2]);
        if (setpoint < 10.0f || setpoint > 30.0f) {
            printf("Error: Setpoint must be between 10.0 and 30.0\n");
            return -1;
        }
        system_state.setpoint = setpoint;
        printf("Setpoint set to %.1f°C\n", setpoint);
        return 0;
    }
    else if (strcmp(argv[1], "power") == 0) {
        int power = atoi(argv[2]);
        if (power < 0 || power > 100) {
            printf("Error: Power must be between 0 and 100\n");
            return -1;
        }
        system_state.output_power = power;
        printf("Output power set to %d%%\n", power);
        return 0;
    }
    else {
        printf("Unknown parameter: %s\n", argv[1]);
        return -1;
    }
}

// 命令: on
int cmd_on(int argc, char* argv[]) {
    if (!system_state.is_connected) {
        printf("Error: Not connected\n");
        return -1;
    }
    
    if (system_state.device_status) {
        printf("Device is already ON\n");
        return 0;
    }
    
    printf("Turning device ON...\n");
    system_state.device_status = 1;
    return 0;
}

// 命令: off
int cmd_off(int argc, char* argv[]) {
    if (!system_state.is_connected) {
        printf("Error: Not connected\n");
        return -1;
    }
    
    if (!system_state.device_status) {
        printf("Device is already OFF\n");
        return 0;
    }
    
    printf("Turning device OFF...\n");
    system_state.device_status = 0;
    system_state.output_power = 0;
    return 0;
}

// 命令: simulate
int cmd_simulate(int argc, char* argv[]) {
    if (!system_state.is_connected) {
        printf("Error: Not connected\n");
        return -1;
    }
    
    // 模拟温度变化
    if (system_state.device_status) {
        // 如果设备开启,温度会朝着设定值移动
        if (system_state.temperature > system_state.setpoint) {
            system_state.temperature -= 0.5f * (system_state.output_power / 100.0f);
        } else {
            system_state.temperature += 0.3f * (system_state.output_power / 100.0f);
        }
    } else {
        // 如果设备关闭,温度会缓慢回到室温
        if (system_state.temperature > 25.0f) {
            system_state.temperature -= 0.2f;
        } else if (system_state.temperature < 25.0f) {
            system_state.temperature += 0.2f;
        }
    }
    
    printf("Temperature updated to %.1f°C\n", system_state.temperature);
    return 0;
}

// 命令: exit
int cmd_exit(int argc, char* argv[]) {
    printf("Exiting...\n");
    
    // 如果连接了,自动断开
    if (system_state.is_connected) {
        printf("Automatically disconnecting...\n");
        cmd_disconnect(0, NULL);
    }
    
    return -100;  // 特殊返回值表示退出
}

// 命令: help
int cmd_help(int argc, char* argv[]) {
    printf("Available commands:\n");
    printf("  help             - Show this help message\n");
    printf("  connect <device> - Connect to device\n");
    printf("  disconnect       - Disconnect from device\n");
    printf("  status           - Show system status\n");
    printf("  set <param> <val>- Set parameter value (setpoint, power)\n");
    printf("  on               - Turn device ON\n");
    printf("  off              - Turn device OFF\n");
    printf("  simulate         - Simulate temperature change\n");
    printf("  exit             - Exit the program\n");
    return 0;
}

// 命令表
Command commands[] = {
    {"help",      "Show available commands", cmd_help},
    {"connect",   "Connect to device", cmd_connect},
    {"disconnect","Disconnect from device", cmd_disconnect},
    {"status",    "Show system status", cmd_status},
    {"set",       "Set parameter value", cmd_set},
    {"on",        "Turn device ON", cmd_on},
    {"off",       "Turn device OFF", cmd_off},
    {"simulate",  "Simulate temperature change", cmd_simulate},
    {"exit",      "Exit the program", cmd_exit},
    {NULL, NULL, NULL}  // 终止表
};

// 解析命令行
int parse_command(char* cmd_line, char* argv[]) {
    int argc = 0;
    char* token;
    
    // 跳过前导空白
    while (isspace(*cmd_line)) cmd_line++;
    
    // 空行
    if (*cmd_line == '\0') return 0;
    
    // 解析命令参数
    token = strtok(cmd_line, " \t\n\r");
    while (token != NULL && argc < MAX_ARGS) {
        argv[argc++] = token;
        token = strtok(NULL, " \t\n\r");
    }
    
    return argc;
}

// 主命令循环
void command_loop() {
    char cmd_line[MAX_CMD_LEN];
    char* argv[MAX_ARGS];
    int argc;
    int i, cmd_found, result;
    
    printf("Simple Command Line Interface\n");
    printf("Type 'help' for available commands\n");
    
    while (1) {
        // 显示提示符
        printf("> ");
        fflush(stdout);
        
        // 读取一行命令
        if (fgets(cmd_line, sizeof(cmd_line), stdin) == NULL) {
            break;
        }
        
        // 解析命令
        argc = parse_command(cmd_line, argv);
        if (argc == 0) continue;  // 空行
        
        // 查找命令
        cmd_found = 0;
        for (i = 0; commands[i].name != NULL; i++) {
            if (strcmp(argv[0], commands[i].name) == 0) {
                result = commands[i].func(argc, argv);
                cmd_found = 1;
                
                // 检查特殊退出代码
                if (result == -100) {
                    return;  // 退出程序
                }
                
                break;
            }
        }
        
        // 命令未找到
        if (!cmd_found) {
            printf("Unknown command: %s\n", argv[0]);
            printf("Type 'help' for available commands\n");
        }
    }
}

int main() {
    command_loop();
    return 0;
}

3. C++上位机开发基础

3.1 基于C++的简单上位机框架

cpp

/**
 * upper_computer_framework.cpp - C++上位机基础框架
 * 演示C++上位机的基本架构设计
 */

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <functional>
#include <thread>
#include <mutex>
#include <chrono>
#include <condition_variable>
#include <atomic>
#include <fstream>
#include <ctime>
#include <iomanip>
#include <memory>

// 前向声明
class Device;
class DataProcessor;
class Logger;
class CommandHandler;

// 设备接口
class Device {
public:
    Device() : connected_(false) {}
    virtual ~Device() { disconnect(); }
    
    virtual bool connect(const std::string& port, int baudRate) {
        if (connected_) {
            std::cout << "Already connected" << std::endl;
            return true;
        }
        
        std::cout << "Connecting to " << port << " at " << baudRate << " baud..." << std::endl;
        
        // 实际实现中需要打开设备
        // 这里仅作演示,假设总是成功
        connected_ = true;
        devicePort_ = port;
        baudRate_ = baudRate;
        
        std::cout << "Connected successfully" << std::endl;
        return true;
    }
    
    virtual void disconnect() {
        if (!connected_) return;
        
        std::cout << "Disconnecting..." << std::endl;
        
        // 实际实现中需要关闭设备
        connected_ = false;
        
        std::cout << "Disconnected" << std::endl;
    }
    
    virtual bool isConnected() const {
        return connected_;
    }
    
    virtual bool sendCommand(const std::string& command) {
        if (!connected_) {
            std::cerr << "Error: Not connected" << std::endl;
            return false;
        }
        
        std::cout << "Sending command: " << command << std::endl;
        
        // 实际实现中需要向设备发送命令
        // 这里仅作演示
        lastCommand_ = command;
        
        return true;
    }
    
    virtual std::string receiveData(int timeout_ms = 1000) {
        if (!connected_) {
            std::cerr << "Error: Not connected" << std::endl;
            return "";
        }
        
        // 实际实现中需要从设备接收数据
        // 这里仅作演示,返回模拟数据
        std::string response = "TEMP=24.5,HUMIDITY=48.2,PRESSURE=1012.3";
        
        std::cout << "Received data: " << response << std::endl;
        return response;
    }
    
protected:
    bool connected_;
    std::string devicePort_;
    int baudRate_;
    std::string lastCommand_;
};

// 数据存储结构
struct SensorData {
    double temperature;
    double humidity;
    double pressure;
    std::chrono::system_clock::time_point timestamp;
    
    SensorData() : temperature(0.0), humidity(0.0), pressure(0.0),
                  timestamp(std::chrono::system_clock::now()) {}
    
    std::string toString() const {
        std::time_t time = std::chrono::system_clock::to_time_t(timestamp);
        std::tm tm = *std::localtime(&time);
        
        std::stringstream ss;
        ss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S") << " | ";
        ss << "Temperature: " << temperature << "°C, ";
        ss << "Humidity: " << humidity << "%, ";
        ss << "Pressure: " << pressure << " hPa";
        
        return ss.str();
    }
};

// 数据处理器
class DataProcessor {
public:
    DataProcessor() : running_(false) {}
    ~DataProcessor() { stop(); }
    
    void process(const std::string& rawData) {
        // 解析原始数据
        SensorData data;
        parseData(rawData, data);
        
        // 添加到数据队列
        {
            std::lock_guard<std::mutex> lock(dataMutex_);
            dataQueue_.push_back(data);
            
            // 限制队列大小
            if (dataQueue_.size() > 1000) {
                dataQueue_.erase(dataQueue_.begin());
            }
        }
        
        // 通知等待的线程
        dataCondition_.notify_all();
    }
    
    void start() {
        if (running_) return;
        
        running_ = true;
        processorThread_ = std::thread(&DataProcessor::processingLoop, this);
    }
    
    void stop() {
        if (!running_) return;
        
        running_ = false;
        dataCondition_.notify_all();
        
        if (processorThread_.joinable()) {
            processorThread_.join();
        }
    }
    
    const std::vector<SensorData>& getDataHistory() const {
        return dataQueue_;
    }
    
    // 注册回调函数,当有新数据处理完成时调用
    void registerCallback(std::function<void(const SensorData&)> callback) {
        dataCallback_ = callback;
    }
    
private:
    void parseData(const std::string& rawData, SensorData& data) {
        // 简单的数据解析,实际应用中可能需要更复杂的解析器
        data.timestamp = std::chrono::system_clock::now();
        
        size_t temp_pos = rawData.find("TEMP=");
        size_t humi_pos = rawData.find("HUMIDITY=");
        size_t pres_pos = rawData.find("PRESSURE=");
        
        if (temp_pos != std::string::npos) {
            size_t end_pos = rawData.find(',', temp_pos);
            if (end_pos == std::string::npos) end_pos = rawData.length();
            
            std::string temp_str = rawData.substr(temp_pos + 5, end_pos - temp_pos - 5);
            data.temperature = std::stod(temp_str);
        }
        
        if (humi_pos != std::string::npos) {
            size_t end_pos = rawData.find(',', humi_pos);
            if (end_pos == std::string::npos) end_pos = rawData.length();
            
            std::string humi_str = rawData.substr(humi_pos + 9, end_pos - humi_pos - 9);
            data.humidity = std::stod(humi_str);
        }
        
        if (pres_pos != std::string::npos) {
            size_t end_pos = rawData.find(',', pres_pos);
            if (end_pos == std::string::npos) end_pos = rawData.length();
            
            std::string pres_str = rawData.substr(pres_pos + 9, end_pos - pres_pos - 9);
            data.pressure = std::stod(pres_str);
        }
    }
    
    void processingLoop() {
        while (running_) {
            SensorData latestData;
            bool hasData = false;
            
            // 等待新数据或停止信号
            {
                std::unique_lock<std::mutex> lock(dataMutex_);
                dataCondition_.wait_for(lock, std::chrono::seconds(1), 
                                       [this] { return !running_ || !dataQueue_.empty(); });
                
                if (!running_) break;
                
                if (!dataQueue_.empty()) {
                    latestData = dataQueue_.back();
                    hasData = true;
                }
            }
            
            // 处理数据
            if (hasData && dataCallback_) {
                // 调用回调函数
                dataCallback_(latestData);
            }
        }
    }
    
private:
    std::vector<SensorData> dataQueue_;
    std::mutex dataMutex_;
    std::condition_variable dataCondition_;
    std::atomic<bool> running_;
    std::thread processorThread_;
    std::function<void(const SensorData&)> dataCallback_;
};

// 日志记录器
class Logger {
public:
    enum class LogLevel {
        DEBUG,
        INFO,
        WARNING,
        ERROR
    };
    
    Logger(const std::string& filename = "upper_computer.log") {
        logFile_.open(filename, std::ios::out | std::ios::app);
        if (!logFile_.is_open()) {
            std::cerr << "Failed to open log file: " << filename << std::endl;
        }
    }
    
    ~Logger() {
        if (logFile_.is_open()) {
            logFile_.close();
        }
    }
    
    void log(LogLevel level, const std::string& message) {
        std::lock_guard<std::mutex> lock(logMutex_);
        
        // 获取当前时间
        auto now = std::chrono::system_clock::now();
        std::time_t time = std::chrono::system_clock::to_time_t(now);
        std::tm tm = *std::localtime(&time);
        
        // 格式化日志消息
        std::stringstream ss;
        ss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S") << " ";
        
        switch (level) {
            case LogLevel::DEBUG:   ss << "[DEBUG] "; break;
            case LogLevel::INFO:    ss << "[INFO] "; break;
            case LogLevel::WARNING: ss << "[WARNING] "; break;
            case LogLevel::ERROR:   ss << "[ERROR] "; break;
        }
        
        ss << message;
        
        // 输出到控制台
        std::cout << ss.str() << std::endl;
        
        // 写入到日志文件
        if (logFile_.is_open()) {
            logFile_ << ss.str() << std::endl;
            logFile_.flush();
        }
    }
    
    void debug(const std::string& message) {
        log(LogLevel::DEBUG, message);
    }
    
    void info(const std::string& message) {
        log(LogLevel::INFO, message);
    }
    
    void warning(const std::string& message) {
        log(LogLevel::WARNING, message);
    }
    
    void error(const std::string& message) {
        log(LogLevel::ERROR, message);
    }
    
private:
    std::ofstream logFile_;
    std::mutex logMutex_;
};

// 命令处理器
class CommandHandler {
public:
    using CommandFunc = std::function<bool(const std::vector<std::string>&)>;
    
    CommandHandler(std::shared_ptr<Device> device,
                  std::shared_ptr<DataProcessor> processor,
                  std::shared_ptr<Logger> logger)
        : device_(device), processor_(processor), logger_(logger) {
        
        // 注册内置命令
        registerCommand("connect", [this](const std::vector<std::string>& args) -> bool {
            if (args.size() < 2) {
                logger_->error("Usage: connect <port> [baudrate]");
                return false;
            }
            
            int baudRate = 9600;  // 默认波特率
            if (args.size() > 2) {
                baudRate = std::stoi(args[2]);
            }
            
            return device_->connect(args[1], baudRate);
        });
        
        registerCommand("disconnect", [this](const std::vector<std::string>& args) -> bool {
            device_->disconnect();
            return true;
        });
        
        registerCommand("send", [this](const std::vector<std::string>& args) -> bool {
            if (args.size() < 2) {
                logger_->error("Usage: send <command>");
                return false;
            }
            
            std::string cmd = args[1];
            for (size_t i = 2; i < args.size(); i++) {
                cmd += " " + args[i];
            }
            
            return device_->sendCommand(cmd);
        });
        
        registerCommand("read", [this](const std::vector<std::string>& args) -> bool {
            int timeout = 1000;  // 默认超时1秒
            if (args.size() > 1) {
                timeout = std::stoi(args[1]);
            }
            
            std::string data = device_->receiveData(timeout);
            if (!data.empty()) {
                processor_->process(data);
                return true;
            }
            return false;
        });
        
        registerCommand("status", [this](const std::vector<std::string>& args) -> bool {
            logger_->info("Device status: " + 
                        std::string(device_->isConnected() ? "Connected" : "Disconnected"));
            
            // 显示最近数据
            const auto& history = processor_->getDataHistory();
            if (!history.empty()) {
                logger_->info("Latest data: " + history.back().toString());
            } else {
                logger_->info("
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小宝哥Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值