#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include "common.h"
#include "snap7.h"

const double eps = 1e-4;
#define Equ(a, b) ((fabs((a) - (b))) < (eps))

/*
	按字符分割
	src 源字符串的首地址(buf的地址) 
	separator 指定的分割字符
	dest 接收子字符串的数组
	num 分割后子字符串的个数
*/
void split(char *src, const char *separator, char **dest, int *num)
{
    char *pNext;
    int count = 0;
    if (src == NULL || strlen(src) == 0) //如果传入的地址为空或长度为0，直接终止
        return;
    if (separator == NULL || strlen(separator) == 0) //如未指定分割的字符串，直接终止
        return;
    pNext = (char *)strtok(src, separator); //必须使用(char *)进行强制类型转换(虽然不写有的编译器中不会出现指针错误)
    while (pNext != NULL)
    {
        *dest++ = pNext;
        ++count;
        pNext = (char *)strtok(NULL, separator); //必须使用(char *)进行强制类型转换
    }
    *num = count;
}

int Check(S7Object Client, int Result, char *function)
{
    int ExecTime;
    char text[1024];
    if (Result == 0)
    {
        return 1;
        Cli_GetExecTime(Client, &ExecTime);
        dy_syslog(LOG_DEBUG, "%s Result: OK Execute time: %d ms", function, ExecTime);
    }
    else
    {
        if (Result < 0)
        {
            dy_syslog(LOG_DEBUG, "%s Library Error: %d", function, Result);
        }
        else
        {
            Cli_ErrorText(Result, text, 1024);
            dy_syslog(LOG_DEBUG, "%s %s", function, text);
        }
    }
    return !Result;
}

int s7_plc_create_conn(s7_plc_client_t *client)
{
    int Requested, Negotiated, res;
    int pdu_size = 1024;

    client->Client = Cli_Create();
    Cli_SetParam(client->Client, p_i32_PDURequest, (void *)&pdu_size);
    res = Cli_ConnectTo(client->Client, client->ip_addr, client->rack, client->slot);

    if (Check(client->Client, res, "UNIT Connection"))
    {
        Cli_GetPduLength(client->Client, &Requested, &Negotiated);
        dy_syslog(LOG_DEBUG, "connect to %s %d %d", client->ip_addr, client->rack, client->slot);
        dy_syslog(LOG_DEBUG, "PDU Requested  : %d bytes Negotiated : %d bytes", Requested, Negotiated);
    };
}

int get_size_from_wordlen(int WordLen)
{
    if (WordLen == 0x01)
    {
        return 1;
    }
    else if (WordLen == 0x02)
    {
        return 1;
    }
    else if (WordLen == 0x04)
    {
        return 2;
    }
    else if (WordLen == 0x06)
    {
        return 4;
    }
    else if (WordLen == 0x08)
    {
        return 4;
    }
    else if (WordLen == 0x1c)
    {
        return 2;
    }
    else if (WordLen = 0x1d)
    {
        return 2;
    }
    return -1;
}

int yuzhi_load_s7_data_cfg(yuzhi_var_t *var, yuzhi_prod_t *prod)
{
    char filename[128] = {0};
    char *data = NULL;
    cJSON *root = NULL;
    cJSON *watches = NULL;
    cJSON *watch = NULL;
    int ret = -1;
    int isjson = 0;
    char buff[128] = {0};

    snprintf(filename, 128, "%s%s.json", YUZHI_DATA_CFG, prod->devicekey);

    data = read_file_data(filename);
    if (data == NULL)
    {
        goto out;
    }

    root = cJSON_Parse(data);
    if (!root)
    {
        goto out;
    }

    GET_JSON_VALUE_INT(root, "isjson", isjson);
    watches = cJSON_GetObjectItem(root, "watchdatas");
    if (watches)
    {
        int cnt = cJSON_GetArraySize(watches);
        int i;

        prod->data = calloc(cnt, sizeof(s7_plc_data_t));
        prod->data_cnt = cnt;
        for (i = 0; i < cnt; i++)
        {
            watch = cJSON_GetArrayItem(watches, i);
            if (isjson == 0)
            {
                GET_JSON_VALUE_STRING(watch, "watchdata", buff);
                if (strlen(buff) > 0)
                {
                    int pk;
                    int pt;
                    int type;
                    int value;
                    char area[8];
                    int addr1;
                    int addr2;
                    int limit_len;
                    int threshold;
                    int decimal_cnt;
                    int rw;
                    char *buf_dup = strdup(buff);
                    char *dest[10];
                    int db_num;
                    int num;
                    char A;

                    s7_plc_data_t *data = &prod->data[i];

                    split(buf_dup, ":", dest, &num);
                    pk = atoi(dest[0]);
                    pt = atoi(dest[1]);
                    type = atoi(dest[2]);
                    strcpy(area, dest[3]);
                    addr1 = atoi(dest[4]);
                    addr2 = atoi(dest[5]);
                    limit_len = atoi(dest[6]);
                    threshold = atoi(dest[7]);
                    decimal_cnt = atoi(dest[8]);
                    rw = atoi(dest[9]);

                    data->pk = pk;
                    data->pt = pt;
                    data->threshold = threshold;
                    data->decimal_cnt = decimal_cnt;
                    data->rw = rw;
                    A = area[0];

                    switch (A)
                    {
                    case 'D':
                        db_num = atoi(area + 1);
                        data->Area = 0x84;
                        data->DBNumber = db_num;
                        break;
                    case 'I':
                        data->Area = 0x81;
                        break;
                    case 'O':
                        data->Area = 0x82;
                        break;
                    case 'M':
                        data->Area = 0x83;
                        break;

                    default:
                        break;
                    }

                    data->Start = addr1;
                    data->Amount = 1;
                    data->type = type;
                    switch (type)
                    {
                    case 0:
                        data->WordLen = 0x01;
                        break;
                    case 3:
                    case 4:
                    case 11:
                    case 13:
                    case 15:
                        data->WordLen = 0x04;
                        break;
                    case 5:
                    case 6:
                    case 12:
                    case 14:
                    case 16:
                        data->WordLen = 0x06;
                        break;
                    case 9:
                        data->WordLen = 0x08;
                        break;
                    case 10:
                        data->WordLen = 0x08;
                        data->Amount = 2;
                        break;
                    case 17:
                        data->WordLen = 0x02;
                        data->Amount = limit_len;
                        break;
                    case 18:
                        data->WordLen = 0x04;
                        break;
                    default:
                        break;
                    }

                    data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                    data->len = get_size_from_wordlen(data->WordLen) * data->Amount;
                    free(buf_dup);
                }
            }
            else
            {
            }
        }
    }

out:
    cJSON_Delete(root);
    return ret;
}

typedef union FLOAT_CONV
{
    float f;
    char c[4];
} float_conv;

typedef union DOUBLE_CONV
{
    double f;
    char c[8];
} double_conv;

float BLEndianFloat(float value)
{
    float_conv d1, d2;
    d1.f = value;
    d2.c[0] = d1.c[3];
    d2.c[1] = d1.c[2];
    d2.c[2] = d1.c[1];
    d2.c[3] = d1.c[0];
    return d2.f;
}

int s7_create_data_report(yuzhi_var_t *var, yuzhi_prod_t *prod, cJSON *items)
{
    int j;
    int report_flag = 0;
    char buff[128] = {0};

    for (j = 0; j < prod->data_cnt; j++)
    {
        s7_plc_data_t *data = &prod->data[j];
        int type = data->type;
        report_flag = 0;

        if (data->Start == 3040)
        {
            dy_syslog(LOG_DEBUG, "reported:%d update:%d type:%d", data->reported, data->update, type);
        }

        if (data->update == 0)
        {
            continue;
        }

        if (data->reported == 0)
        {
            report_flag = 1;
        }

        switch (type)
        {
        case 0:
        {
            unsigned char bit = ((unsigned char *)data->pdata)[0];
            if (report_flag == 0)
            {
                if (bit != data->val.bit)
                {
                    report_flag = 1;
                    data->val.bit = bit;
                }
            }
            else
            {
                data->val.bit = bit;
            }
            if (report_flag == 1)
            {
                snprintf(buff, sizeof(buff), "%d", bit);
            }
            break;
        }
        case 3:
        {
            short v16 = *(short *)(data->pdata);
            v16 = ntohs(v16);
            double v = (double)v16;
            double a = 1.0;
            if (data->decimal_cnt != 0)
            {
                a = pow(10, data->decimal_cnt);
                v = v / a;
            }

            if (data->reported == 0)
            {
                // 第一条数据总是要上报
                report_flag = 1;
            }
            else
            {
                if (data->threshold == 0)
                {
                    if (!Equ(v16, data->val.v16))
                    {
                        // 没有设置同步阈值，且数据有变化，上报且更新缓存数据
                        report_flag = 1;
                    }
                }
                else
                {
                    // 设置了同步阈值
                    double old = ((double)(data->val.v16)) / a;
                    if (fabs(v - old) > data->threshold)
                    {
                        report_flag = 1;
                    }
                }
            }
            if (report_flag == 1)
            {
                // 更新缓存数据
                data->val.v16 = v16;
                snprintf(buff, sizeof(buff), "%g", v);
            }
            break;
        }
        case 4:
        {
            unsigned short uv16 = *(short *)(data->pdata);
            uv16 = ntohs(uv16);
            double v = (double)uv16;
            double a = 1.0;
            if (data->decimal_cnt != 0)
            {
                a = pow(10, data->decimal_cnt);
                v = v / a;
            }

            if (data->reported == 0)
            {
                // 第一条数据总是要上报
                report_flag = 1;
            }
            else
            {
                if (data->threshold == 0)
                {
                    if (!Equ(uv16, data->val.uv16))
                    {
                        // 没有设置同步阈值，且数据有变化，上报且更新缓存数据
                        report_flag = 1;
                    }
                }
                else
                {
                    // 设置了同步阈值
                    double old = ((double)(data->val.uv16)) / a;
                    if (fabs(v - old) > data->threshold)
                    {
                        report_flag = 1;
                    }
                }
            }
            if (report_flag == 1)
            {
                // 更新缓存数据
                data->val.uv16 = uv16;
                snprintf(buff, sizeof(buff), "%g", v);
            }
            break;
        }
        case 5:
        {
            int v32 = *(short *)(data->pdata);
            v32 = ntohs(v32);
            double v = (double)v32;
            double a = 1.0;
            if (data->decimal_cnt != 0)
            {
                a = pow(10, data->decimal_cnt);
                v = v / a;
            }

            if (data->reported == 0)
            {
                // 第一条数据总是要上报
                report_flag = 1;
            }
            else
            {
                if (data->threshold == 0)
                {
                    if (!Equ(v32, data->val.v32))
                    {
                        // 没有设置同步阈值，且数据有变化，上报且更新缓存数据
                        report_flag = 1;
                    }
                }
                else
                {
                    // 设置了同步阈值
                    double old = ((double)(data->val.v32)) / a;
                    if (fabs(v - old) > data->threshold)
                    {
                        report_flag = 1;
                    }
                }
            }
            if (report_flag == 1)
            {
                // 更新缓存数据
                data->val.v32 = v32;
                snprintf(buff, sizeof(buff), "%g", v);
            }
            break;
        }
        case 6:
        {
            int uv32 = *(short *)(data->pdata);
            uv32 = ntohs(uv32);
            double v = (double)uv32;
            double a = 1.0;
            if (data->decimal_cnt != 0)
            {
                a = pow(10, data->decimal_cnt);
                v = v / a;
            }

            if (data->reported == 0)
            {
                // 第一条数据总是要上报
                report_flag = 1;
            }
            else
            {
                if (data->threshold == 0)
                {
                    if (!Equ(uv32, data->val.uv32))
                    {
                        // 没有设置同步阈值，且数据有变化，上报且更新缓存数据
                        report_flag = 1;
                    }
                }
                else
                {
                    // 设置了同步阈值
                    double old = ((double)(data->val.uv32)) / a;
                    if (fabs(v - old) > data->threshold)
                    {
                        report_flag = 1;
                    }
                }
            }
            if (report_flag == 1)
            {
                // 更新缓存数据
                data->val.uv32 = uv32;
                snprintf(buff, sizeof(buff), "%g", v);
            }
            break;
        }
        case 9:
        {
            float_conv d;
            d.c[0] = ((char *)(data->pdata))[3];
            d.c[1] = ((char *)(data->pdata))[2];
            d.c[2] = ((char *)(data->pdata))[1];
            d.c[3] = ((char *)(data->pdata))[0];
            float f = d.f;
            double v = (double)f;
            double a = 1.0;
            if (data->decimal_cnt != 0)
            {
                a = pow(10, data->decimal_cnt);
                v = v / a;
            }

            if (data->reported == 0)
            {
                // 第一条数据总是要上报
                report_flag = 1;
            }
            else
            {
                if (data->threshold == 0)
                {
                    if (!Equ(v, data->val.f))
                    {
                        // 没有设置同步阈值，且数据有变化，上报且更新缓存数据
                        report_flag = 1;
                    }
                }
                else
                {
                    // 设置了同步阈值
                    double old = (double)(data->val.f);
                    if (fabs(v - old) > data->threshold)
                    {
                        report_flag = 1;
                    }
                }
            }
            if (report_flag == 1)
            {
                // 更新缓存数据
                data->val.f = v;
                snprintf(buff, sizeof(buff), "%g", v);
            }
            break;
        }
        case 10:
        {
            double_conv d;
            d.c[0] = ((char *)(data->pdata))[7];
            d.c[1] = ((char *)(data->pdata))[6];
            d.c[2] = ((char *)(data->pdata))[5];
            d.c[3] = ((char *)(data->pdata))[4];
            d.c[4] = ((char *)(data->pdata))[3];
            d.c[5] = ((char *)(data->pdata))[2];
            d.c[6] = ((char *)(data->pdata))[1];
            d.c[7] = ((char *)(data->pdata))[0];
            double f = d.f;
            double v = f;
            double a = 1.0;
            if (data->decimal_cnt != 0)
            {
                a = pow(10, data->decimal_cnt);
                v = v / a;
            }
            if (data->reported == 0)
            {
                // 第一条数据总是要上报
                report_flag = 1;
            }
            else
            {
                if (data->threshold == 0)
                {
                    if (!Equ(v, data->val.d))
                    {
                        // 没有设置同步阈值，且数据有变化，上报且更新缓存数据
                        report_flag = 1;
                    }
                }
                else
                {
                    // 设置了同步阈值
                    double old = data->val.d;
                    if (fabs(v - old) > data->threshold)
                    {
                        report_flag = 1;
                    }
                }
            }
            if (report_flag == 1)
            {
                // 更新缓存数据
                data->val.d = v;
                snprintf(buff, sizeof(buff), "%g", v);
            }
            break;
        }
        case 11:
        {
            unsigned short uv16 = *(unsigned short *)(data->pdata);
            if (report_flag == 0)
            {
                if (uv16 != data->val.bcd16)
                {
                    report_flag = 1;
                    data->val.bcd16 = uv16;
                }
            }
            else
            {
                data->val.bcd16 = uv16;
            }
            if (report_flag)
            {
                snprintf(buff, sizeof(buff), PRINTF_BINARY_PATTERN_INT16, PRINTF_BYTE_TO_BINARY_INT16(uv16));
            }
            break;
        }
        case 12:
        {
            unsigned int uv32 = *(unsigned int *)(data->pdata);
            if (report_flag == 0)
            {
                if (uv32 != data->val.bcd32)
                {
                    report_flag = 1;
                    data->val.bcd32 = uv32;
                }
            }
            else
            {
                data->val.bcd32 = uv32;
            }
            if (report_flag)
            {
                snprintf(buff, sizeof(buff), PRINTF_BINARY_PATTERN_INT32, PRINTF_BYTE_TO_BINARY_INT32(uv32));
            }
            break;
        }
        case 13:
        {
            unsigned short uv16 = *(unsigned short *)(data->pdata);
            uv16 = ntohs(uv16);
            if (report_flag == 0)
            {
                if (uv16 != data->val.bin16)
                {
                    report_flag = 1;
                    data->val.bin16 = uv16;
                }
            }
            else
            {
                data->val.bin16 = uv16;
            }
            if (report_flag == 1)
            {
                snprintf(buff, sizeof(buff), PRINTF_BINARY_PATTERN_INT16, PRINTF_BYTE_TO_BINARY_INT16(uv16));
            }
            break;
        }
        case 14:
        {
            unsigned int uv32 = *(unsigned int *)(data->pdata);
            uv32 = ntohl(uv32);
            if (report_flag == 0)
            {
                if (uv32 != data->val.bin32)
                {
                    report_flag = 1;
                    data->val.bin32 = uv32;
                }
            }
            else
            {
                data->val.bin32 = uv32;
            }
            if (report_flag == 1)
            {
                snprintf(buff, sizeof(buff), PRINTF_BINARY_PATTERN_INT32, PRINTF_BYTE_TO_BINARY_INT32(uv32));
            }
            break;
        }
        case 15:
        {
            unsigned short uv16 = *(unsigned short *)(data->pdata);
            uv16 = ntohs(uv16);
            if (report_flag == 0)
            {
                if (uv16 != data->val.hex16)
                {
                    report_flag = 1;
                    data->val.hex16 = uv16;
                }
            }
            else
            {
                data->val.hex16 = uv16;
            }
            if (report_flag == 1)
            {
                snprintf(buff, sizeof(buff), "%02X%02X", ((uv16 >> 8) & 0xFF), uv16 & 0xFF);
            }
            break;
        }
        case 16:
        {
            unsigned int uv32 = *(unsigned int *)(data->pdata);
            uv32 = ntohl(uv32);
            if (report_flag == 0)
            {
                if (uv32 != data->val.hex32)
                {
                    report_flag = 1;
                    data->val.hex32 = uv32;
                }
            }
            else
            {
                data->val.hex32 = uv32;
            }
            if (report_flag == 1)
            {
                snprintf(buff, sizeof(buff), "%02X%02X%02X%02X", ((uv32 >> 24) & 0xFF), ((uv32 >> 16) & 0xFF), ((uv32 >> 8) & 0xFF), uv32 & 0xFF);
            }
            break;
        }
        case 17:
        {
            char *ptr = (char *)data->pdata;
            if (data->val.text == NULL)
            {
                data->val.text = calloc(1, data->Amount + 1);
                report_flag = 1;
            }
            if (strlen(ptr) > 0 && data->val.text != NULL && strcmp(ptr, data->val.text) != 0)
            {
                report_flag = 1;
                strcpy(data->val.text, ptr);
            }
            if (report_flag)
            {
                snprintf(buff, sizeof(buff), "%s", ptr);
            }
            break;
        }
        case 18:
        {
            unsigned short dog = *(unsigned short *)(data->pdata);
            dog = ntohs(dog);
            if (report_flag == 0)
            {
                if (dog != data->val.dog)
                {
                    report_flag = 1;
                    data->val.dog = dog;
                }
            }
            else
            {
                data->val.dog = dog;
            }
            if (report_flag)
            {
                snprintf(buff, sizeof(buff), "%u", dog);
            }
            break;
        }
        default:
            break;
        }

        if (report_flag == 1)
        {
            cJSON *item = cJSON_CreateObject();
            cJSON_AddNumberToObject(item, "pk", data->pk);
            cJSON_AddNumberToObject(item, "pt", data->pt);
            cJSON_AddStringToObject(item, "type", "change");
            cJSON_AddStringToObject(item, "result", buff);
            cJSON_AddItemToArray(items, item);
            data->reported = 1;
        }
    }
}

int yuzhi_edit_s7_data(yuzhi_var_t *var, yuzhi_prod_t *prod, cJSON *watches)
{
    int cnt = cJSON_GetArraySize(watches);
    int i;
    char buff[128] = {0};
    cJSON *watch;

    for (i = 0; i < cnt; i++)
    {
        watch = cJSON_GetArrayItem(watches, i);

        GET_JSON_VALUE_STRING(watch, "watchdata", buff);

        if (strlen(buff) > 0)
        {
            int pk;
            int pt;
            int type;
            int value;
            char area[8];
            int addr1;
            int addr2;
            int limit_len;
            int threshold;
            int decimal_cnt;
            char *buf_dup = strdup(buff);
            char *dest[10];
            int db_num;
            int num;
            char A;
            int j = 0;
            int find = 0;
            s7_plc_data_t *t = NULL;
            s7_plc_data_t data_tmp = {0};
            s7_plc_data_t *data = &data_tmp;

            split(buf_dup, ":", dest, &num);
            pk = atoi(dest[0]);
            pt = atoi(dest[1]);
            type = atoi(dest[2]);
            strcpy(area, dest[3]);
            addr1 = atoi(dest[4]);
            addr2 = atoi(dest[5]);
            limit_len = atoi(dest[6]);
            threshold = atoi(dest[7]);
            decimal_cnt = atoi(dest[8]);
            for (j = 0; j < prod->data_cnt; j++)
            {
                t = &prod->data[j];
                if (t->pk == pk)
                {
                    find = 1;
                    break;
                }
            }

            if (find == 0 || t == NULL)
            {
                dy_syslog(LOG_WARNING, "not find pk");
                continue;
            }
            if (t->rw == 0)
            {
                dy_syslog(LOG_WARNING, "read only pk");
                continue;
            }

            A = area[0];
            switch (A)
            {
            case 'D':
                db_num = atoi(area + 1);
                data->Area = 0x84;
                data->DBNumber = db_num;
                break;
            case 'I':
                data->Area = 0x81;
                break;
            case 'O':
                data->Area = 0x82;
                break;
            case 'M':
                data->Area = 0x83;
                break;
            case 'E':
                data->Area = 0;
            default:
                break;
            }

            data->Start = addr1;
            data->Amount = 1;
            data->type = type;
            if (data->Area != 0)
            {
                switch (type)
                {
                case 0:
                {
                    int val = atoi(dest[9]);
                    if (val != 0 && val != 1)
                    {
                        break;
                    }
                    data->WordLen = 0x01;
                    data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                    *(unsigned char *)(data->pdata) = val;
                    break;
                }
                case 3:
                case 4:
                {
                    double d = atof(dest[9]);
                    double a = 1.0;
                    if (t->decimal_cnt > 0)
                    {
                        a = pow(10, t->decimal_cnt);
                        d = d * a;
                    }
                    unsigned short v = d;
                    dy_syslog(LOG_DEBUG, "v:%d", v);
                    data->WordLen = 0x04;
                    data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                    *(unsigned short *)(data->pdata) = htons(v);
                    break;
                }
                case 5:
                case 6:
                {
                    double d = atof(dest[9]);
                    if (t->decimal_cnt > 0)
                    {
                        int a = pow(10, t->decimal_cnt);
                        d = d * a;
                    }
                    unsigned int v = d;
                    data->WordLen = 0x06;
                    data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                    *(unsigned int *)(data->pdata) = htonl(v);
                    break;
                }
                case 9:
                {
                    data->WordLen = 0x08;
                    data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                    float_conv d;
                    double f = atof(dest[9]);
                    if (t->decimal_cnt > 0)
                    {
                        int a = pow(10, t->decimal_cnt);
                        f = f * a;
                    }
                    d.f = (float)f;
                    ((char *)(data->pdata))[0] = d.c[3];
                    ((char *)(data->pdata))[1] = d.c[2];
                    ((char *)(data->pdata))[2] = d.c[1];
                    ((char *)(data->pdata))[3] = d.c[0];
                    break;
                }
                case 10:
                {
                    data->WordLen = 0x08;
                    data->Amount = 2;
                    data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                    double_conv d;
                    double f = atof(dest[9]);
                    if (t->decimal_cnt > 0)
                    {
                        int a = pow(10, t->decimal_cnt);
                        f = f * a;
                    }
                    d.f = f;
                    ((char *)(data->pdata))[0] = d.c[7];
                    ((char *)(data->pdata))[1] = d.c[6];
                    ((char *)(data->pdata))[2] = d.c[5];
                    ((char *)(data->pdata))[3] = d.c[4];
                    ((char *)(data->pdata))[4] = d.c[3];
                    ((char *)(data->pdata))[5] = d.c[2];
                    ((char *)(data->pdata))[6] = d.c[1];
                    ((char *)(data->pdata))[7] = d.c[0];
                    break;
                }
                case 11:
                {
                    unsigned int d = 0;
                    int i = 0;
                    const char *pch = dest[9];
                    int flag = 0;
                    dy_syslog(LOG_DEBUG, "data:%s", pch);
                    while (1)
                    {
                        if (*pch == '0' || *pch == '1')
                        {
                            d <<= 1;
                            d |= *pch++ - '0';
                            i++;
                        }
                        else if (*pch == 0)
                        {
                            break;
                        }
                        else
                        {
                            dy_syslog(LOG_DEBUG, "i:%d = %d", i, *pch);
                            flag = 1;
                            break;
                        }
                    }
                    if (i > 16)
                    {
                        flag = 1;
                    }
                    if (flag == 0)
                    {
                        data->WordLen = 0x04;
                        data->Amount = 1;
                        data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                        *(unsigned short *)(data->pdata) = htons((unsigned short)d);
                    }
                    else
                    {
                        dy_syslog(LOG_ERR, "data is wrong");
                    }
                    break;
                }
                case 12:
                {
                    unsigned int d = 0;
                    int i = 0;
                    const char *pch = dest[9];
                    int flag = 0;
                    while (1)
                    {
                        if (*pch == '0' || *pch == '1')
                        {
                            d <<= 1;
                            d |= *pch++ - '0';
                            i++;
                        }
                        else if (*pch == 0)
                        {
                            break;
                        }
                        else
                        {
                            flag = 1;
                            break;
                        }
                    }
                    if (i > 32)
                    {
                        flag = 0;
                    }
                    if (flag == 0)
                    {
                        data->Amount = 1;
                        data->WordLen = 0x06;
                        data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                        *(unsigned int *)(data->pdata) = htonl(d);
                    }
                    else
                    {
                        dy_syslog(LOG_ERR, "data is wrong");
                    }
                    break;
                }
                case 13:
                {
                    unsigned int d = 0;
                    int i = 0;
                    const char *pch = dest[9];
                    int flag = 0;
                    dy_syslog(LOG_DEBUG, "data:%s", pch);
                    while (1)
                    {
                        if (*pch == '0' || *pch == '1')
                        {
                            d <<= 1;
                            d |= *pch++ - '0';
                            i++;
                        }
                        else if (*pch == 0)
                        {
                            break;
                        }
                        else
                        {
                            dy_syslog(LOG_DEBUG, "i:%d = %d", i, *pch);
                            flag = 1;
                            break;
                        }
                    }
                    if (i > 16)
                    {
                        flag = 1;
                    }
                    if (flag == 0)
                    {
                        data->WordLen = 0x04;
                        data->Amount = 1;
                        data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                        *(unsigned short *)(data->pdata) = htons((unsigned short)d);
                    }
                    else
                    {
                        dy_syslog(LOG_ERR, "data is wrong");
                    }
                    break;
                }
                case 14:
                {
                    unsigned int d = 0;
                    int i = 0;
                    const char *pch = dest[9];
                    int flag = 0;
                    while (1)
                    {
                        if (*pch == '0' || *pch == '1')
                        {
                            d <<= 1;
                            d |= *pch++ - '0';
                            i++;
                        }
                        else if (*pch == 0)
                        {
                            break;
                        }
                        else
                        {
                            flag = 1;
                            break;
                        }
                    }
                    if (i > 32)
                    {
                        flag = 0;
                    }
                    if (flag == 0)
                    {
                        data->Amount = 1;
                        data->WordLen = 0x06;
                        data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                        *(unsigned int *)(data->pdata) = htonl(d);
                    }
                    else
                    {
                        dy_syslog(LOG_ERR, "data is wrong");
                    }
                    break;
                }
                case 15:
                {
                    char *endptr;
                    long val;
                    unsigned short u16;
                    int flag = 0;

                    errno = 0;
                    val = strtol(dest[9], &endptr, 16);

                    if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0))
                    {
                        perror("strtol");
                        flag = 1;
                    }

                    if (endptr == dest[9])
                    {
                        fprintf(stderr, "No digits were found\n");
                        flag = 1;
                    }

                    if (flag == 0)
                    {
                        u16 = (unsigned short)val;
                        data->WordLen = 0x04;
                        data->Amount = 1;
                        data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                        *(unsigned short *)(data->pdata) = htons((unsigned short)u16);
                    }
                    break;
                }
                case 16:
                {
                    char *endptr;
                    long val;
                    unsigned int u32;
                    int flag = 0;

                    errno = 0;
                    val = strtol(dest[9], &endptr, 16);

                    if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0))
                    {
                        perror("strtol");
                        flag = 1;
                    }

                    if (endptr == dest[9])
                    {
                        fprintf(stderr, "No digits were found\n");
                        flag = 1;
                    }

                    if (flag == 0)
                    {
                        u32 = (unsigned int)val;
                        data->WordLen = 0x06;
                        data->Amount = 1;
                        data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                        *(unsigned int *)(data->pdata) = htonl((unsigned int)u32);
                    }
                    break;
                }
                case 17:
                    data->WordLen = 0x02;
                    data->Amount = limit_len;
                    data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                    strcpy((char *)data->pdata, dest[9]);
                    break;
                case 18:
                    data->WordLen = 0x04;
                    data->pdata = calloc(data->Amount, get_size_from_wordlen(data->WordLen));
                    *(unsigned short *)(data->pdata) = htons(atoi(dest[9]));
                    break;
                default:
                    break;
                }

                if (data->pdata != NULL)
                {
                    int Result = Cli_WriteArea(prod->s7_plc_client->Client, data->Area, data->DBNumber, data->Start, data->Amount, data->WordLen, data->pdata);
                    dy_syslog_hex(LOG_DEBUG, data->pdata, data->Amount * get_size_from_wordlen(data->WordLen), "edit data, pk:%d addr:%d data->pdata:%p", pk, data->Start, data->pdata);
                    if (Check(prod->s7_plc_client->Client, Result, "write Area"))
                    {
                        dy_syslog(LOG_DEBUG, "write");
                    }
                    else
                    {
                        dy_syslog(LOG_DEBUG, "write failed");
                    }

                    free(data->pdata);
                }
            }

            free(buf_dup);
        }
    }
}

void *s7_run_loop(void *param)
{
    yuzhi_var_t *var = (yuzhi_var_t *)param;
    int IsConnected = 0;

    while (1)
    {
        int i = 0;
        yuzhi_prod_t *prod = NULL;

        for (i = 0; i < var->prod_cnt; i++)
        {
            prod = &var->prods[i];
            if (prod->plctype == 5)
            {
                //Siemens
                int j = 0;

                int res = Cli_GetConnected(prod->s7_plc_client->Client, &IsConnected);
                if (Check(prod->s7_plc_client->Client, res, "get connected"))
                {
                    if (IsConnected == 0)
                    {
                        Cli_Connect(prod->s7_plc_client->Client);
                    }
                    Cli_GetConnected(prod->s7_plc_client->Client, &IsConnected);
                    if (IsConnected != 0)
                    {
                        // dy_syslog(LOG_DEBUG, "data_cnt:%d", prod->data_cnt);
                        for (j = 0; j < prod->data_cnt; j++)
                        {
                            s7_plc_data_t *data = &prod->data[j];
                            if (data->Area <= 0)
                            {
                                continue;
                            }
                            res = Cli_ReadArea(prod->s7_plc_client->Client, data->Area,
                                               data->DBNumber, data->Start, data->Amount,
                                               data->WordLen, data->pdata);
                            if (Check(prod->s7_plc_client->Client, res, "read Area"))
                            {
                                // dy_syslog_hex(LOG_DEBUG, data->pdata, data->len, "Got data:pk:%d type:%d", data->pk, data->type);
                                data->update = 1;
                            }
                            else
                            {
                                dy_syslog(LOG_DEBUG, "read data failed, pk:%d", data->pk);
                            }
                        }
                    }
                }
                {
                    int Status;
                    res = Cli_GetPlcStatus(prod->s7_plc_client->Client, &Status);
                    if (Check(prod->s7_plc_client->Client, res, "CPU Status"))
                    {
                        prod->cpuStatus = Status;
                    }
                    else
                    {
                        prod->cpuStatus = -1;
                    }
                }
            }
        }
        msleep(100);
    }
}