#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include "common.h"


static int period_service_poll(modbus_shmem_var_t *var)
{
    TIMER_CONFIRM(var->period_poll_timer);
    long long now = get_time_stamp_ms();
    int port_index = 0;
    return 0;
}

static void modbus_shmem_loop(modbus_shmem_var_t *var)
{
    int ret = -1, maxfd, i;
    fd_set rset;
    struct timeval timeout;

    while (1)
    {
        SELECT_INIT();
        SELECT_ADD_FD(var->period_poll_timer);
        timeout.tv_usec = 0;
        timeout.tv_sec = 5;

        ret = select(maxfd + 1, &rset, 0, 0, &timeout);
        if (ret < 0)
        {
            int error = errno;
            dy_syslog(LOG_INFO, "errno %d\n", error);

            if (error == EINTR)
            {
                continue;
            }
            else
            {
                break;
            }
        }
        else if (ret > 0)
        {
            if (var->period_poll_timer > 0 && FD_ISSET(var->period_poll_timer, &rset))
            {
                FD_CLR(var->period_poll_timer, &rset);
                period_service_poll(var);
            }
        }
    }
}


int modbus_shmem_init(modbus_shmem_var_t *var)
{
    get_board_sn(var->sn_str);
    dy_syslog(LOG_INFO, "board SN:%s", var->sn_str);
    var->reg_data = malloc(sizeof(reg_data_t));
    reg_data_t *reg_data = var->reg_data;
    var->period_poll_timer = my_timer_create();
    if (var->period_poll_timer > 0)
    {
        my_timer_set(var->period_poll_timer, 1, 1000);
    }

    modbus_shmem_init_modbus_tcp_slave(var);

    reg_data->mb_mapping = modbus_mapping_new_start_address(0, 0, 0, 0, var->reg_start, var->reg_number*2, 0, 0);
    // reg_data->data = reg_data->mb_mapping->tab_registers;
    free(reg_data->mb_mapping->tab_registers);
    reg_data->mb_mapping->tab_registers = share_mem_init("/tmp",var->shmem_addr , (var->reg_start + var->reg_number)*2);
    reg_data->data = reg_data->mb_mapping->tab_registers;
    return 0;
}

static void print_help(void) {
    printf("Usage: modbus_shmem        [-p port] modbus slave port;default 506 \n");
    printf("                           [-a modbus address] modbus address;default 1 \n");
    printf("                           [-i shmem id] shmem id of shmem;default 1 \n");
    printf("                           [-s start] register start addr;default 0 \n");
    printf("                           [-n number] number of register;default 1 \n");
    printf("                           [-h] show this help and exit \n");
}

static void modbus_shmem_opt(int argc, char *argv[],modbus_shmem_var_t *var)
{
    int c;
    //初始化默认参数
    var->port = 506;
    var->slave_addr = 1;
    var->shmem_addr = 1;
    var->reg_start = 0;
    var->reg_number = 1;
    while ((c = getopt(argc, argv, "p:a:i:s:n:h")) != -1) {
        switch (c) {
            case 'p':
                if (optarg)
                    var->port = atoi(optarg);
                else {
                    print_help();
                    exit(1);
                }
                break;
            case 'a':
                if (optarg)
                    var->slave_addr = atoi(optarg);
                else {
                    print_help();
                    exit(1);
                }
                break;
            case 'm':
                if (optarg)
                    var->shmem_addr = atoi(optarg);
                else {
                    print_help();
                    exit(1);
                }
                break;
            case 'r':
                if (optarg)
                    var->reg_start = atoi(optarg);
                else {
                    print_help();
                    exit(1);
                }
                break;
            case 'n':
                if (optarg)
                    var->reg_number = atoi(optarg);
                else {
                    print_help();
                    exit(1);
                }
                break;
            case 'h':
            case '?':
            default:
                print_help();
                exit(0);
        }
    }
}

int main(int argc, char *argv[])
{
    int c = 0;
    modbus_shmem_var_t var = {0};
    memset(&var, 0, sizeof(var));
    modbus_shmem_opt(argc,argv,&var);
    modbus_shmem_init(&var);
    modbus_shmem_loop(&var);

    return 0;
}
