////
//// Created by DELL on 2024/10/16.1
/*
 * 2025年1月24日，新风加湿机控制部分，解决通讯短暂断开故障
 * 2025年1月25日，增加新风除湿机
 *
*/////
#include "main.h"
#include "constants_is_three.h"
#include "modbus.h"
#include "usart.h"
#include "cmsis_os2.h"
#include "mini_gateway_master.h"
#include "modbus_slave.h"

static nmbs_t nmbs;
uint8_t slaves_2[SLAVE_ADDRESS_END] = {0}; // 保存已经存在的从站号
uint8_t power_count = 0; //
static osMutexId_t constants_is_three_key;

void search_3constants_slave();

static int32_t uart_read(uint8_t *buf, uint16_t count, int32_t byte_timeout_ms,
                         void *arg) {
    HAL_StatusTypeDef status = HAL_UART_Receive(&huart3, buf, count, byte_timeout_ms);
    if (status == HAL_OK) {
        return count;
    } else {
        return 0;
    }
}

static int32_t uart_write(const uint8_t *buf, uint16_t count, int32_t byte_timeout_ms,
                          void *arg) {
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
    HAL_UART_Transmit(&huart3, buf, count, byte_timeout_ms);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
    return count;
}

//// task
_Noreturn void constants_is_three_poll_task(void *pv) {
    for (;;) {
        if (osMutexAcquire(constants_is_three_key, osWaitForever) == osOK) {
            search_3constants_slave();
            osMutexRelease(constants_is_three_key);
        }
        osDelay(1000 * 60 * 1);
    }
}

bool get_three_constants_status_2(ffx_status_t *three_constants_Status) {
    uint8_t data1[2] = {0};
    data1[0] = get_reg_value(POWER_REG_ADDRESS);
    if (data1[0] == 0) {
        power_count++;
    }
    if ((power_count >= 10)||(data1[0] == 1)) {
        nmbs_error err = nmbs_write_multiple_registers(&nmbs, THREE_CONSTANTS_POWER_REG_ADDRESS, 1, &data1);
        three_constants_Status->power = data1[0];
        power_count = 0;
        if (err != NMBS_ERROR_NONE) {
            return false;
        }
    }
    nmbs_error err = nmbs_read_holding_registers(&nmbs, THREE_CONSTANTS_ERRORS_REG_ADDRESS, 1, &data1);
    three_constants_Status->errors = data1[0];
    set_reg_value(INNER_ERROR4_REG_ADDRESS, three_constants_Status->errors);
    if (err != NMBS_ERROR_NONE) {
        return false;
    }
    return true;
}

//除湿机控制
bool get_dry_status(ffx_status_t *dry_Status) {
    uint16_t data[4] = {0};
    data[0] = get_reg_value(POWER_REG_ADDRESS);
    dry_Status->fresh_air_system = get_reg_value(FRESH_AIR_MODE_REG_ADDRESS);
    dry_Status->fan_speed = get_reg_value(FAN_SPEED_REG_ADDRESS);
    switch (dry_Status->fresh_air_system) {
        case 2://
            data[1] = 1;
            break;
        case 4://
            data[1] = 0;
            break;
        default:
            break;
    }
    switch (dry_Status->fan_speed) {
        case 1://
            data[2] = 1;
            break;
        case 2://
            data[2] = 1;
            break;
        case 3://
            data[2] = 2;
            break;
        case 4://
            data[2] = 2;
            break;
        case 5://
            data[2] = 3;
            break;
        default:
            break;
    }
    data[3] = 60;
    if (!data[0]) {
        power_count++;
    }
    if ((power_count >= 3)||(data[0] == 1)) {
        nmbs_error err = nmbs_write_multiple_registers(&nmbs, DRY_POWER_REG_ADDRESS, 4, &data[0]);
        dry_Status->power = data[0];
        if (err != NMBS_ERROR_NONE) {
            return false;
        }
        power_count = 0;
    }
    nmbs_error err = nmbs_read_holding_registers(&nmbs, DRY_ERRORS_REG_ADDRESS, 1, &data);
    dry_Status->errors = data[0];
    set_reg_value(INNER_ERROR4_REG_ADDRESS, dry_Status->errors);
    if (err != NMBS_ERROR_NONE) {
        return false;
    }
    return true;
}

_Noreturn void constants_is_three_poll_mater_task_2(void *pv) {
    for (;;) {
        if (osMutexAcquire(constants_is_three_key, osWaitForever) == osOK) {
            bool fresh_air_flag = false;
            for (int i = 0; i < sizeof(slaves_2); i++) {
                if (slaves_2[i] == 20) {        //新风除湿机，站号20
                    ffx_status_t Dry_Status;
                    nmbs_set_destination_rtu_address(&nmbs, slaves_2[i]);
                    if ((get_reg_value(POWER_REG_ADDRESS) == 0)) {
                        DEBUG_PRINTF("The REG_POWER_ADDRESS is 0.\r\n");
                    }
                    if (get_dry_status(&Dry_Status) && Dry_Status.power == 1) {
                        set_reg_value(FRESH_AIR_REG_ADDRESS, slaves_2[i]);
                    }
                } else if ((slaves_2[i] != 0) && (slaves_2[i] != 20)) {     //新风加湿机，站号7~10
                    ffx_status_t three_constants_Status;
                    nmbs_set_destination_rtu_address(&nmbs, slaves_2[i]);
                    if ((get_reg_value(POWER_REG_ADDRESS) == 0)) {
                        DEBUG_PRINTF("The REG_POWER_ADDRESS is 0.\r\n");
                    }
                    if (get_three_constants_status_2(&three_constants_Status) &&
                        three_constants_Status.power == 1) {
                        set_reg_value(FRESH_AIR_REG_ADDRESS, slaves_2[i]);
                        uint16_t fresh_air_reg[5] = {0};
                        fresh_air_reg[0] = get_reg_value(WORK_MODE_REG_ADDRESS);
                        fresh_air_reg[1] = get_reg_value(FRESH_AIR_MODE_REG_ADDRESS);
                        fresh_air_reg[2] = get_reg_value(FAN_SPEED_REG_ADDRESS);
                        fresh_air_reg[3] = get_reg_value(HUMP_ON_FFX_ADDRESS);
                        fresh_air_reg[4] = get_reg_value(HUMP_OFF_FFX_ADDRESS);
                        nmbs_error err = nmbs_write_multiple_registers(&nmbs, THREE_CONSTANTS_MODE_REG_ADDRESS, 2,
                                                                       &fresh_air_reg[1]);
                        osDelay(200);
                        err = nmbs_write_multiple_registers(&nmbs, THREE_CONSTANTS_HUMP_ON_REG_ADDRESS, 2,
                                                            &fresh_air_reg[3]);
                    }
                    osDelay(1000);
                }
            }
            osMutexRelease(constants_is_three_key);
            osDelay(1000);
        }
    }
}
//// 检测从机是否存在
bool check_slave_exist_2(uint8_t slave_addr) {
    nmbs_set_destination_rtu_address(&nmbs, slave_addr);
    uint16_t result;
    osDelay(10);
    nmbs_error err = nmbs_read_holding_registers(&nmbs, 0x01, 1, &result);
    return err == NMBS_ERROR_NONE;
}

//// 轮询从站
void search_3constants_slave() {
    for (int i = SLAVE_ADDRESS_START_2; i <= SLAVE_ADDRESS_END_2; i++) {
        bool exist = check_slave_exist_2(i);
        if (exist != NMBS_ERROR_NONE) {
            slaves_2[i - 7] = i;
            set_reg_value(INNER_ERROR2_REG_ADDRESS, 0);
        }
        osDelay(10);
        if (exist == NMBS_ERROR_NONE) {
            exist = check_slave_exist_2(i);
            if (exist != NMBS_ERROR_NONE) {
                slaves_2[i - 7] = i;
                set_reg_value(INNER_ERROR2_REG_ADDRESS, 0);
            } else {
                set_reg_value(INNER_ERROR2_REG_ADDRESS, 1);
            }
        }
        osDelay(10);
    }
    bool exist = check_slave_exist_2(SLAVE_ADDRESS_END_3);
    if (exist != NMBS_ERROR_NONE) {
        slaves_2[4] = 20;
        set_reg_value(INNER_ERROR2_REG_ADDRESS, 0);
    }
    osDelay(10);
    if (exist == NMBS_ERROR_NONE) {
        exist = check_slave_exist_2(SLAVE_ADDRESS_END_3);
        if (exist != NMBS_ERROR_NONE) {
            slaves_2[4] = 20;
            set_reg_value(INNER_ERROR2_REG_ADDRESS, 0);
        } else {
            set_reg_value(INNER_ERROR2_REG_ADDRESS, 1);
        }
    }
    osDelay(100);
}

void constants_is_three_master_init() {
    constants_is_three_key = osMutexNew(NULL);
    nmbs_platform_conf platformConf;// 配置uart
    nmbs_platform_conf_create(&platformConf);
    platformConf.transport = NMBS_TRANSPORT_RTU;// RTU
    platformConf.read = &uart_read;     // 读写函数
    platformConf.write = &uart_write;   // 读写函数
    nmbs_client_create(&nmbs, &platformConf);// 创建客户端
    nmbs_set_read_timeout(&nmbs, 400);
    nmbs_set_byte_timeout(&nmbs, 400);
    // 开启轮询任务
    osThreadNew(constants_is_three_poll_task, NULL, NULL);
    osThreadNew(constants_is_three_poll_mater_task_2, NULL, NULL);
}

