//
// Created by DELL on 2024/10/16.
//

#include <stdint.h>
#include "mini_gateway_master.h"
#include "usart.h"
#include "modbus.h"
#include "cmsis_os2.h"
#include "modbus_slave.h"

uint8_t error_count = 0;
static nmbs_t nmbs;
extern uint8_t slaves[SLAVE_ADDRESS_END]; // 保存已经存在的从站号
//static osMutexId_t mini_mutex;
extern uint8_t is_slave_exist;
static uint8_t coil[INNER_SLAVE_ADDRESS_END] = {0};

static int32_t uart_read(uint8_t *buf, uint16_t count, int32_t byte_timeout_ms,
                         void *arg) {
    HAL_StatusTypeDef status = HAL_UART_Receive(&huart4, 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(GPIOA, GPIO_PIN_15, GPIO_PIN_SET);
    HAL_UART_Transmit(&huart4, buf, count, byte_timeout_ms);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);
    return count;
}

void sync_ac_status(ffx_status_t *status) {
    uint16_t power;
    uint16_t mode;
    uint16_t fan_speed;
    uint16_t set_temp;
    if (status->power == 0x01) {
        power = 0xAA;
        fan_speed = status->fan_speed + 1;
        set_temp = status->set_temp;
    } else
        power = 0x55;
    mode = status->mode + 1;
    switch (status->mode) {
        case 0://制冷模式
            mode = status->mode + 1;
            break;
        case 1://制热模式
            mode = status->mode + 3;
            break;
        case 2://除湿模式
            mode = status->mode;
            break;
        case 3://送风模式
            mode = status->mode;
            break;
        case 4://加湿模式、送风
            mode = 3;
            break;
        default:
            break;
    }
    uint16_t regs[5] = {power, mode, set_temp * 10, fan_speed, 0};
    nmbs_error err2 = nmbs_write_multiple_registers(&nmbs, 102 + 25 * (status->inner_num - 1), 5, regs);
    if (err2 == NMBS_ERROR_NONE) {
        set_reg_value(INNER_ERROR1_REG_ADDRESS, 0);
        error_count = 0;
    } else {
        set_reg_value(INNER_ERROR1_REG_ADDRESS, 1);
        error_count++;
    }
}

_Noreturn void mini_mater_task(void *pv) {
    uint8_t is_error_ffx[8] = {0};
    for (;;) {
//        if (osMutexAcquire(mini_mutex, osWaitForever) == osOK) {
            bool is_power_on = false;
            ffx_status_t status;
            for (int i = 0; i < sizeof(coil); i++) {
                if (coil[i] != 0) {
                    uint16_t data[10];
                    uint8_t inner_num = i + 1;
                    nmbs_error err = nmbs_read_holding_registers(&nmbs,
                                                                 (MINI_GATEWAY_INNER_POWER_ADDRESS + 25 * i),
                                                                 4, &data[0]);
                    if (err == NMBS_ERROR_NONE) {
                        status.power = data[0];
                        status.mode = data[1];
                        status.fan_speed = data[3] - 2;
                        status.set_temp = data[2] / 10;
                        status.inner_num = inner_num;
                        if ((status.power == INNER_POWER_ON) && (is_power_on == false)) {
                            osDelay(100);
                            is_power_on = true;
                            set_reg_value(POWER_REG_ADDRESS, status.power);
                            set_reg_value(WORK_MODE_REG_ADDRESS, status.mode);
                            set_reg_value(FAN_SPEED_REG_ADDRESS, status.fan_speed);
                            set_reg_value(SET_TEMP_REG_ADDRESS, status.set_temp);
                            set_reg_value(INNER_ERROR1_REG_ADDRESS, 0);
                            error_count = 0;
                        }
                    } else {
                        error_count++;
                        is_error_ffx[i]++;
                        is_power_on = true;
                        if ((status.power == INNER_POWER_OFF) && is_error_ffx[i] > 3) {
                            set_reg_value(INNER_ERROR1_REG_ADDRESS, 1);
                            set_reg_value(POWER_REG_ADDRESS, status.power);
                            error_count = 0;
                            is_error_ffx[i] = 0;
                        }
                    }
                }
                osDelay(1000);
            }
            if ((status.power == INNER_POWER_OFF) && (is_power_on == false)) {
                set_reg_value(INNER_ERROR1_REG_ADDRESS, 0);
                set_reg_value(POWER_REG_ADDRESS, status.power);
                error_count = 0;
            }
            osDelay(1000);
//            osMutexRelease(mini_mutex);
//        }
    }
}

// 检测从机是否存在
bool check_inner_slave_exist(uint8_t slave_addr) {
    nmbs_set_destination_rtu_address(&nmbs, slave_addr);    // 设置从机地址
    bool result;
    osDelay(100);
    nmbs_read_coils(&nmbs, MINI_GATEWAY_INNER_COIL_ADDRESS + slave_addr - 1, 1, &result);
    if (result) {
        return true;
    } else {
        return false;
    }
}

_Noreturn void gateway_poll_task(void *pv) {
    uint8_t count = 0;
    for (;;) {
        nmbs_bitfield regs = {0};
//        if (osMutexAcquire(mini_mutex, osWaitForever) == osOK) {
            for (int i = 0; i <= INNER_SLAVE_ADDRESS_END; i++) {
                coil[i] = 0;
            }
            nmbs_error err1 = nmbs_read_coils(&nmbs, MINI_GATEWAY_INNER_COIL_ADDRESS, 8, &regs[0]);
            nmbs_read_coils(&nmbs, MINI_GATEWAY_INNER_COIL2_ADDRESS, 8, &regs[1]);
            nmbs_read_coils(&nmbs, MINI_GATEWAY_INNER_COIL_ERROR3_ADDRESS, 1, &regs[3]);
            nmbs_read_coils(&nmbs, MINI_GATEWAY_INNER_COIL_ERROR4_ADDRESS, 1, &regs[4]);
            osDelay(500);
            if (err1 == NMBS_ERROR_NONE) {
                set_reg_value(INNER_GROUP1_REG_ADDRESS, regs[0]);
                set_reg_value(INNER_GROUP2_REG_ADDRESS, regs[1]);
                set_reg_value(INNER_ERROR1_REG_ADDRESS, 0);
                set_reg_value(INNER_ERROR3_REG_ADDRESS, regs[3] << 2);
                set_reg_value(INNER_ERROR4_REG_ADDRESS, regs[4] << 3);
                error_count = 0;
                uint8_t buf;
                for (int i = 0; i <= INNER_SLAVE_ADDRESS_END; i++) {
                    buf = (regs[0] - is_slave_exist) << (7 - i);
                    coil[i] = buf >> (7);
                }
            } else {
                nmbs_error err2 = nmbs_read_coils(&nmbs, MINI_GATEWAY_INNER_COIL_ADDRESS, 8, &regs[0]);
                osDelay(300);
                if (err2 == NMBS_ERROR_NONE) {
                    uint8_t buf;
                    for (int i = 0; i <= INNER_SLAVE_ADDRESS_END; i++) {
                        buf = (regs[0] - is_slave_exist) << (7 - i);
                        coil[i] = buf >> (7);
                    }
                    error_count = 0;
                    set_reg_value(INNER_GROUP1_REG_ADDRESS, regs[0]);
                }
            }
            count--;
            osDelay(500);
//            osMutexRelease(mini_mutex);
            osDelay(1000 * 60 * 10);
//        }
    }
}

void mini_gateway_master_init(void) {
//    mini_mutex = osMutexNew(NULL);
    nmbs_platform_conf platformConf;// 配置uart
    nmbs_platform_conf_create(&platformConf);
    platformConf.transport = NMBS_TRANSPORT_RTU;// RTU
    platformConf.read = &uart_read;     // 读写函数1
    platformConf.write = &uart_write;   // 读写函数
    nmbs_client_create(&nmbs, &platformConf);// 创建客户端
    nmbs_set_read_timeout(&nmbs, 300);
    nmbs_set_byte_timeout(&nmbs, 300);
    nmbs_set_destination_rtu_address(&nmbs, MINI_GATEWAY_SLAVE_ADDRESS);

    osThreadNew(gateway_poll_task, NULL, NULL);
    osThreadNew(mini_mater_task, NULL, NULL);
}
