#include <jni.h>
#include <string>

#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <android/log.h>
#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <time.h>
#include "GPIOControl.h"
#include "WeatherComm.h"

SIO_PARAM_SERIAL_DEF serialport;
float weatherpntmsg[10];

static void set_baudrate (struct termios *opt, unsigned int baudrate)
{
    cfsetispeed(opt, baudrate);
    cfsetospeed(opt, baudrate);
}

static void set_data_bit (struct termios *opt, unsigned int databit)
{
    opt->c_cflag &= ~CSIZE;
    switch (databit)
    {
        case 8:
            opt->c_cflag |= CS8;
            break;
        case 7:
            opt->c_cflag |= CS7;
            break;
        case 6:
            opt->c_cflag |= CS6;
            break;
        case 5:
            opt->c_cflag |= CS5;
            break;
        default:
            opt->c_cflag |= CS8;
            break;
    }
}

static void set_parity (struct termios *opt, char parity)
{
    switch (parity)
    {
        case'N':/* 无校验 */
        case 'n':
            opt->c_cflag &= ~PARENB;
            break;
        case'E':/*偶校验*/
        case 'e':
            opt->c_cflag |= PARENB;
            opt->c_cflag &= ~PARODD;
            break;
        case'O':/* 奇校验 */
        case 'o':
            opt->c_cflag |= PARENB;
            opt->c_cflag |= ~PARODD;
            break;
        default: /*其它选择为无校验 */
            opt->c_cflag &= ~PARENB;
            break;
    }
}

static void set_stopbit (struct termios *opt, const char *stopbit)
{
    if (strcmp(stopbit, "1") == 0)
    {
        opt->c_cflag &= ~CSTOPB;/*1 位停止位 t */
    }
    else if(0 == strcmp(stopbit, "1.5"))
    {
        opt->c_cflag &= ~CSTOPB;/*1.5 位停止位 */
    }
    else if(0 == strcmp (stopbit,"2"))
    {
        opt->c_cflag |= CSTOPB; /*2 位停止位 */
    }
    else
    {
        opt->c_cflag &= ~CSTOPB; /*1 位停止位 */
    }
}

int set_port_attr (int fd, int baudrate, int databit, const char *stopbit, char parity, int vtime, int vmin )
{
    struct termios opt;
    tcgetattr(fd, &opt);
    set_baudrate(&opt, baudrate);
    //opt.c_cflag |= CLOCAL|CREAD; /*|CRTSCTS */
    opt.c_lflag &= ~(ICANON | ECHO |ECHOE |ISIG);
    set_data_bit(&opt, databit);
    set_parity(&opt, parity);
    set_stopbit(&opt, stopbit);
    opt.c_oflag = 0;
    //opt.c_lflag |= 0;
    opt.c_oflag &= ~OPOST;
    opt.c_cc[VTIME] = vtime;
    opt.c_cc[VMIN] = vmin;
    tcflush (fd, TCIFLUSH);
    return (tcsetattr (fd, TCSANOW, &opt));
}

static void setInt(int cmd, int value)
{
    int fd = open("/dev/mtkgpioctrl", O_RDONLY);
    IOT_PARAM param;
    param.cmd = cmd;
    param.value = value;
    // LOGE("set_int fd=%d,cmd=%d,value=%d\r\n",fd, cmd, value);
    if( fd > 0 )
    {
        int res = ioctl(fd, IOT_PARAM_WRITE, &param);
        // LOGE("set_int22 cmd=%d,value=%d,result=%d\r\n",param.cmd, param.value, param.result);
        close(fd);
    }
    return;
}
static void setRS485Enable(bool z) {
    setInt(CMD_SET_485_EN_STATE, z ? 1 : 0);
}

static void set485WriteMode() {
    setInt(CMD_SET_485_STATE, 1);
}

static void set485ReadMode() {
    setInt(CMD_SET_485_STATE, 0);
}
static void set12VEnable(bool z) {
    setInt(CMD_SET_12V_EN_STATE, z ? 1 : 0);
}

static void setCam3V3Enable(bool enabled)
{
    setInt(CMD_SET_CAM_3V3_EN_STATE, enabled ? 1 : 0);
}


/*********************************************************************************
*						            气象数据处理							         *
**********************************************************************************/
void PortDataProcess( void )
{
    float			fvalue, fcorvalue, *fvalua, frnb/*, fwind*/;
    //WORD		uDevAddr;
    unsigned char		cmdidx;
    int			i, j, aipnt, datanum;
    SIO_PARAM_SERIAL_DEF	*pPortParam;
    char			szbuf[64];

    pPortParam = &serialport;
    //取出装置地址,开始处理地址+++
    if(0x02 == pPortParam->m_au8RecvBuf[5])
    {
        //pPortParam->devaddr = pPortParam->m_au8RecvBuf[4];
        return;
    }
    cmdidx = pPortParam->m_au8RecvBuf[5];
#if 0
    aipnt = pPortParam->SameTypeDevIdx;
    uDevAddr = serialport->m_au8RecvBuf[4];
    if(0 == srdt.IsReadWireTem)
    {
        if(uDevAddr != pPortParam->devaddr)
            return;
    }
#endif
    fvalua = &fvalue;
    datanum = pPortParam->m_au8RecvBuf[6];
    if((0x08 != cmdidx) && (0x09 != cmdidx))
        return;

    for(i = 0, j=7; (i<datanum) && (j<6+pPortParam->m_au8RecvBuf[1]); i++, j+=5 )
    {
        if(0x08 == cmdidx)
            fvalue = (pPortParam->m_au8RecvBuf[j+1]<<24)+(pPortParam->m_au8RecvBuf[j+2]<<16)
                     +(pPortParam->m_au8RecvBuf[j+3]<<8)+pPortParam->m_au8RecvBuf[j+4];
        else
        {
            *(u_char *)fvalua = pPortParam->m_au8RecvBuf[j+4];
            *((u_char *)fvalua+1) = pPortParam->m_au8RecvBuf[j+3];
            *((u_char *)fvalua+2) = pPortParam->m_au8RecvBuf[j+2];
            *((u_char *)fvalua+3) = pPortParam->m_au8RecvBuf[j+1];
        }
        switch(pPortParam->m_au8RecvBuf[j])
        {
            case	1:	/*温度*/
                weatherpntmsg[0] = fvalue;
                LOGE("温度:%0.3f  ", fvalue);
                break;
            case	2:	/*气压*/
                weatherpntmsg[5] = fvalue;
                LOGE("气压:%0.3f  ", fvalue);
                break;
            case	3:	/*湿度*/
                weatherpntmsg[1] = fvalue;
                LOGE("湿度:%0.3f  ", fvalue);
                break;
            case	4:	/*雨量*/
                break;
            case	5:	/*日照*/
                break;
            case	6:	/*风速*/
                weatherpntmsg[2] = fvalue;
                LOGE("风速:%0.3f  ", fvalue);
                break;
            case	7:	/*风向*/
                weatherpntmsg[3] = fvalue;
                LOGE("风向:%0.3f  ", fvalue);
                break;
            case	8:	/*拉力*/
            case	9:	/*倾角传感器X轴倾角*/
            case	10:	/*倾角传感器Y轴倾角*/
            case	11:	/*测温球导线温度*/
            case	12:	/*测温球内部温度*/
                break;
            case	13:	/*测温球导线X轴倾角*/
                break;
            case	14:	/*测温球导线Y轴倾角*/
                break;
            case	15:	/*测温球导线电流*/
                break;
            case	16:	/*测温球电池电压*/
                break;
            case	17: /*A相泄漏电流平均值；*/
                break;
            case	18: /*A相泄漏电流最大值；*/
                break;
            case	19: /*A相超过3mA的脉冲频次*/
                break;
            case	20: /*A相超过10mA的脉冲频次*/
                break;
            case	21: /*B相泄漏电流平均值；*/
                break;
            case	22: /*B相泄漏电流最大值；*/
                break;
            case	23: /*B相超过3mA的脉冲频次*/
                break;
            case	24: /*B相超过10mA的脉冲频次*/
            case	25: /*C相泄漏电流平均值；*/
            case	26: /*C相泄漏电流最大值；*/
            case	27: /*C相超过3mA的脉冲频次*/
            case	28: /*C相超过10mA的脉冲频次*/
                break;
        }
    }
}

//***************************************************************
//*    		     		按照协议格式化接收数据				*
//***************************************************************
static void RecvData(u_char *buf, int len)// 规约读数据处理
{
    int  				i, ictime;
    //WORD				crc, check;
    SIO_PARAM_SERIAL_DEF	*pPortParam;

    pPortParam = &serialport;
    ictime = (int)time(NULL);

    if(pPortParam->m_iRecvLen == 0)
    {
        pPortParam->iRecvTime = ictime;
    }
    else
    {
        if((ictime-pPortParam->iRecvTime > 6) || (ictime - pPortParam->iRecvTime < 0))
            pPortParam->iRecvTime = ictime;
        else if(ictime - pPortParam->iRecvTime > 2)
        {
            pPortParam->m_iRecvLen = 0;
            pPortParam->m_iRevStatus = 0;
        }
    }

    for(i=0; i<len; i++)
    {
        switch(pPortParam->m_iRevStatus)
        {
            case 0:			// 0x68
                pPortParam->m_iRecvLen = 0;
                pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
                if(0x68 == buf[i])
                    pPortParam->m_iRevStatus++;
                else
                    pPortParam->m_iRevStatus = 18;
                break;
            case 1:			// len1
                pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
                pPortParam->m_iRevStatus++;
                break;
            case 2:			// len2
                pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
                if(buf[i] == pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen-2])
                {
                    pPortParam->m_iRevStatus++;
                    pPortParam->m_iNeedRevLength = buf[i]+5;
                }
                else
                    pPortParam->m_iRevStatus = 18;
                break;
            case 3:			// 0x68
                pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
                pPortParam->m_iNeedRevLength--;
                if(0x68 == buf[i])
                    pPortParam->m_iRevStatus++;
                else
                    pPortParam->m_iRevStatus = 18;
                break;
            case 4:	// 正确接收数据
                pPortParam->m_iNeedRevLength--;
                pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
                if(pPortParam->m_iNeedRevLength > 0)
                    break;
                if(buf[i] != 0x16)
                {
                    pPortParam->m_iRevStatus=18;
                    break;
                }

                //if(CheckLpcError(serialport->m_au8RecvBuf, pPortParam->m_iRecvLen) == TRUE)
                {
                    PortDataProcess();
                    pPortParam->m_iRevStatus = 0;
                    pPortParam->RevCmdFlag = 1;
                }
                 pPortParam->m_iRecvLen = 0;
                break;
            case 255:// 错误接收数据
            default:
                if(buf[i] == 0x68)
                {
                    pPortParam->m_iRevStatus = 1;
                    pPortParam->m_iRecvLen = 1;
                    pPortParam->m_au8RecvBuf[0] = buf[i];
                }
                else if(buf[i] == 0x16)
                {
                    pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
                    pPortParam->m_iRevStatus = 0;
                    pPortParam->m_iRecvLen = 0;
                }
                else
                {
                    pPortParam->m_au8RecvBuf[pPortParam->m_iRecvLen++] = buf[i];
                    if(pPortParam->m_iRecvLen > 200)
                    {
                        pPortParam->m_iRecvLen = 0;
                    }
                }
                break;
        }
    }
}

//int inum =0;
//int itimecnt=0;
static int weather_comm(SERIAL_PARAM weatherport)
{
    int fd = -1;
    int len, i,ret, ictime, iruntime, isendtime, irecvtime, icnt=0;
    unsigned char sendbuf[] = {0x68,0x00,0x00,0x68,0x01,0x09,0x0a,0x16};
    char recvbuf[256], szbuf[512];
    //char serial_description[] = "/dev/ttyS0";

#if 0
    DIR *dir = opendir("/dev");
    if (dir == NULL) {
        LOGE("_test_ opendir");
        return -1;
    }

    // 读取目录项
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        // 过滤出串口设备，通常以"ttyS"或"ttyUSB"开头
        if ((strncmp(entry->d_name, "ttyS2", 5) == 0) ||
            (strncmp(entry->d_name, "ttyS0", 5) == 0)) {
            LOGE("_test_ Found serial port: %s\n", entry->d_name);
        }
    }

    // 关闭目录
    closedir(dir);
#endif
    serialport.RevCmdFlag = 1;
    serialport.m_iRecvLen = 0;
    serialport.m_iRevStatus = 0;

    set12VEnable(true);
    setCam3V3Enable(true);
    setRS485Enable(true);

    ictime = (int)time(NULL);
    for(;;)
    {
        if(fd < 0)
        {
            fd = open(weatherport.pathname, O_RDWR | O_NDELAY);
            //fd = open(weatherport.pathname, O_RDWR | O_NOCTTY);
            if(fd < 0)
            {
                LOGE("_test_ open serial error \n");
                perror(weatherport.pathname);
                return -1;
            }

            ret= set_port_attr (fd, weatherport.baudrate,weatherport.databit,weatherport.stopbit,weatherport.parity,0,0 );/*9600 8n1 */
            if(ret < 0)
            {
                LOGE("_test_ set uart arrt faile \n");
                return -1;
            }
        }

        usleep(10000);
        iruntime = (int)time(NULL);
        if((iruntime - ictime > 120) || (iruntime - ictime < 0))
            ictime = iruntime;
        if(iruntime - ictime > 19)
        {
            memset(szbuf, 0, sizeof(szbuf));
            sprintf(szbuf, "气象采样时间=%d,停止采样!", iruntime-ictime);
            LOGE("%s", szbuf);
            break;
        }

        if(1 == serialport.RevCmdFlag)
        {
            set485WriteMode();

            len = write(fd, sendbuf, sizeof(sendbuf));/* 向串囗发送字符串 */
            serialport.RevCmdFlag = 0;
            isendtime = time(NULL);
            if (len < 0) {
                LOGE("write data error \n");
                return -1;
            } else {
                memset(szbuf, 0, sizeof(szbuf));
                sprintf(szbuf, "Send：");
                for (i = 0; i < len; i++) {
                    sprintf(szbuf, "%s %02X", szbuf, sendbuf[i]);
                }
                LOGE("%s", szbuf);
                //icnt = 0;
                //inum++;
            }
            tcdrain(fd);
            //usleep(50000);
        }
        else
        {
            irecvtime = time(NULL);
            if((irecvtime-isendtime > 6) ||(irecvtime - isendtime < 0))
                isendtime = irecvtime;
            if (irecvtime-isendtime > 1)
            {
                LOGE("传感器超过%d秒未应答", irecvtime-isendtime);
                serialport.RevCmdFlag = 1;
                serialport.m_iRecvLen = 0;
                serialport.m_iRevStatus = 0;
                close(fd);
                //set12VEnable(false);
                //setCam3V3Enable(false);
                //setRS485Enable(false);
                fd = -1;
                continue;
            }
        }
        set485ReadMode();
        memset(recvbuf, 0, sizeof(recvbuf));
        len = read(fd, recvbuf, sizeof(recvbuf));/* 在串口读取字符串 */
        if (len < 0) {
            LOGE("serial read error \n");
            continue;
        }
        if(0 == len)
        {
            //icnt++;
            continue;
        }

        memset(szbuf, 0, sizeof(szbuf));
        sprintf(szbuf, "Recv：");
        for (i = 0; i < len; i++) {
            sprintf(szbuf, "%s %02X", szbuf, recvbuf[i]);
        }
        __android_log_print(ANDROID_LOG_INFO, "serial", "%s", szbuf);
        RecvData((u_char*)recvbuf, len);
        //LOGE("一周期空循环次数%d, 读取次数%d, 时间：%d %d", icnt, inum, (int)time(NULL), itimecnt);
        icnt = 0;
        //serialport.RevCmdFlag =1;
    }

    close(fd);
    set12VEnable(false);
    setCam3V3Enable(false);
    setRS485Enable(false);

    //exit(-1);
    return(0);
}

int serial_port_comm()
{
    SERIAL_PARAM  portparm;
#if 1
    memset(portparm.pathname, 0, sizeof(portparm.pathname));
    sprintf(portparm.pathname, "/dev/ttyS0");
    portparm.parity = 'N';
    portparm.databit = 8;
    portparm.baudrate = B9600;
    memset(portparm.stopbit, 0, sizeof(portparm.stopbit));
    sprintf(portparm.stopbit, "1");
#endif
    //itimecnt = (int)time(NULL);

    for(;;)
        weather_comm(portparm);
    return 0;
}

