//
// Created by DELL on 2024/10/16.1
//
//#include "semphr.h"
#include "main.h"
#include "ffx_master.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[SLAVE_ADDRESS_END+1] = {0}; // 保存已经存在的从站号
static uint8_t index_2 = 0;
//static osMutexId_t ffx_mutex;
extern uint8_t error_count;
uint8_t buffer_reg[10]; // 保存读取到的寄存器值
void search_ffx_slave();
osMutexId_t mutexHandle;

uint8_t is_slave_exist = 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(&huart2, 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_1, GPIO_PIN_SET);
    HAL_UART_Transmit(&huart2, buf, count, byte_timeout_ms);
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);
    return count;
}

// task
_Noreturn void ffx_poll_task(void *pv) {
    for (;;) {
//        if (osMutexAcquire(ffx_mutex, osWaitForever) == osOK) {
        osStatus_t status = osMutexAcquire(mutexHandle, osWaitForever);
        if (status == osOK){
            search_ffx_slave();
//            osMutexRelease(ffx_mutex);
            osMutexRelease(mutexHandle);
        }
        osDelay(1000 * 60 * 1);
    }
}

bool get_ffx_status(ffx_status_t *ffxStatus) {
    uint16_t ffx_ststus[5] = {0};
    nmbs_error err = nmbs_read_holding_registers(&nmbs, POWER_FFX_ADDRESS, 5, ffx_ststus);
    if (err == NMBS_ERROR_NONE) {
        ffxStatus->power = ffx_ststus[0];
        ffxStatus->mode = ffx_ststus[1];
        ffxStatus->fresh_air_system = ffx_ststus[2];
        ffxStatus->fan_speed = ffx_ststus[4];
        if((ffxStatus->power == 0)){
            DEBUG_PRINTF("The FFX_POWER_REG_ADDRESS is 0.\r\n");
        }
    }else {
        return false;
    }
    uint16_t data[2] = {0};
    err = nmbs_read_holding_registers(&nmbs, SET_TEMP_FFX_ADDRESS, 1, &data[0]);
    if (err == NMBS_ERROR_NONE) {
        ffxStatus->set_temp = data[0];
    }
    err = nmbs_read_holding_registers(&nmbs, HUMP_ON_FFX_ADDRESS, 2, &data[0]);
    if (err == NMBS_ERROR_NONE) {
        ffxStatus->humidity_on = data[0];
        ffxStatus->humidity_off = data[1];
    }
    err = nmbs_read_holding_registers(&nmbs, INNER_NUM_FFX_ADDRESS, 1, &data[0]);
    if (err == NMBS_ERROR_NONE) {
        ffxStatus->inner_num = data[0];
    }
    return true;
}


_Noreturn void ffx_mater_task(void *pv) {
    uint8_t error_count = 0;
//    uint8_t is_error_ffx[8] = {0};
    for (;;) {
//        if (osMutexAcquire(ffx_mutex, osWaitForever) == osOK) {
        osStatus_t status = osMutexAcquire(mutexHandle, osWaitForever);
//        set_reg_value(FRESH_AIR_MODE_REG_ADDRESS, 4);
        if (status == osOK){
            bool fresh_air_flag = false;
            for (int j = 0; j <= sizeof(slaves); j++) {
                if (slaves[j] != 0) {
                    ffx_status_t ffxStatus;
                    nmbs_set_destination_rtu_address(&nmbs, slaves[j]);
                    if ((get_ffx_status(&ffxStatus)) && (ffxStatus.power == 1)) {
                        set_reg_value(HUMP_ON_FFX_ADDRESS, ffxStatus.humidity_on);
                        set_reg_value(HUMP_OFF_FFX_ADDRESS, ffxStatus.humidity_off);
                        set_reg_value(INNER_ERROR2_REG_ADDRESS, 0);
                        nmbs_write_multiple_registers(&nmbs, INNER_GROUP1_REG_ADDRESS, 1, &ffxStatus.power);
                        osDelay(300);
//                        DEBUG_PRINTF("Read that FFX exists: %d.\r\n", slaves[j]);
//                        is_error_ffx[i] = 0;
                        error_count = 0;
                        if(ffxStatus.fresh_air_system != 2)
                            set_reg_value(FRESH_AIR_MODE_REG_ADDRESS, 4);
                        else set_reg_value(FRESH_AIR_MODE_REG_ADDRESS, 2);
                        if(ffxStatus.fresh_air_system == 2)
                            fresh_air_flag = true;
                    } else {
                        error_count++;
                        if (error_count >= 10) {
                            set_reg_value(INNER_ERROR2_REG_ADDRESS, 1);
                        }
                    }
                    sync_ac_status(&ffxStatus);
                    ffxStatus.power = 0;
                    ffxStatus.inner_num = 0xAA;
                    ffxStatus.mode = 0;
                    ffxStatus.fan_speed = 0;
                    osDelay(1000);
                    uint16_t ffx_BUF[2] ;
                    ffx_BUF[0] = get_reg_value(FRESH_AIR_REG_ADDRESS);
                    ffx_BUF[1] = get_reg_value(INNER_ERROR4_REG_ADDRESS);
                    nmbs_write_multiple_registers(&nmbs, FLESH_AIR_ERROR_FFX_ADDRESS, 2, &ffx_BUF[0]);
                    osDelay(1000);
                }
            }
//            osMutexRelease(ffx_mutex);
            osMutexRelease(mutexHandle);
        }
        osDelay(1000);
    }
}

// 检测从机是否存在
bool check_slave_exist(uint8_t slave_addr) {
    nmbs_set_destination_rtu_address(&nmbs, slave_addr);
    uint16_t result;
    osDelay(100);
    nmbs_error err = nmbs_read_holding_registers(&nmbs, 0x01, 1, &result);
    return err == NMBS_ERROR_NONE;
}

// 轮询从站
void search_ffx_slave() {
    for (int i = SLAVE_ADDRESS_START; i <= SLAVE_ADDRESS_END; i++) {
        ffx_status_t ffxStatusquery;
        bool exist = check_slave_exist(i);
        if (exist) {
            slaves[i] = i;
            set_reg_value(INNER_ERROR2_REG_ADDRESS, 0);
//            exist = false;
        }
        osDelay(200);
        if (exist == NMBS_ERROR_NONE) {
            exist = check_slave_exist(i);
            if (exist != NMBS_ERROR_NONE) {
                slaves[i] = i;
                set_reg_value(INNER_ERROR2_REG_ADDRESS, 0);
            } else {
                set_reg_value(INNER_ERROR2_REG_ADDRESS, 1);
//                ffxStatusquery.inner_num = i;
//                ffxStatusquery.power = 0;
//                sync_ac_status(&ffxStatusquery);
//                osDelay(100);
            }
        }
        osDelay(200);
    }
}

void ffx_master_init() {
//    ffx_mutex = osMutexNew(NULL);
    mutexHandle = 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(ffx_poll_task, NULL, NULL);
    osThreadNew(ffx_mater_task, NULL, NULL);
}

