#include "stdio.h"
#include "PLCDevice.h"
#include <iostream>
#include <common.h>
#include <QDebug>

extern SysConf g_sys_conf;

bool PLCDevice::init_plc(PLCDevice* PLCptr)
{
    // modbus_connect() 建立连接，成功返回0，错误返回-1
    // modbus_new_rtu 生成RTU的连接，建立成功则返回指向modbus_t结构的指针，否则将返回NULL/0

    const char* comport = g_sys_conf.ComPort.data();
    qDebug() << "COM:" << comport;
    //连接PLC
    PLCptr->g_modbus = modbus_new_rtu(comport, 9600, 'N', 8, 1);
    modbus_set_debug(PLCptr->g_modbus, 0);	// 用flag设置debug调试标志位，flag=1时显示modbus消息的字节
    modbus_set_response_timeout(PLCptr->g_modbus, 1, 0);	// 设置响应超时
    modbus_connect(PLCptr->g_modbus);
    modbus_set_slave(PLCptr->g_modbus, 1);	// 设置从站id

    uint8_t data;
    int ret = modbus_read_bits(PLCptr->g_modbus, 30000, 1, &data);
    if (PLCptr->g_modbus && ret == -1) {
        PLCptr->g_plc_ok = false;
    }
    else {

        PLCptr->g_plc_ok = true;
    }
    return true;
}

bool PLCDevice::init_plc_tcp(PLCDevice* PLCptr)
{
    // modbus_connect() 建立连接，成功返回0，错误返回-1
    // modbus_new_rtu 生成RTU的连接，建立成功则返回指向modbus_t结构的指针，否则将返回NULL/0

    PLCptr->g_modbus = modbus_new_tcp("192.168.1.1", 7002);
	qDebug("new g_modbus:\t%p\n", PLCptr->g_modbus);
	modbus_set_debug(PLCptr->g_modbus, 0);
	modbus_set_response_timeout(PLCptr->g_modbus, 1, 0);	// 设置响应超时
	modbus_connect(PLCptr->g_modbus);
	modbus_set_slave(PLCptr->g_modbus, 1);	// 设置从机地址
	int nRet = modbus_connect(PLCptr->g_modbus);// 连接设备
	// 连接失败
	if (-1 == nRet)
	{
        PLCptr->g_plc_ok = false;
		qDebug("connect failed:%s\n", modbus_strerror(errno));
		return false;
	}
    PLCptr->g_plc_ok = true;
    return true;
}

bool PLCDevice::disconnect_plc(void)
{
    if (g_modbus)
    {
        modbus_close(g_modbus);
        modbus_free(g_modbus);
    }
    return true;
}

int PLCDevice::write_bit_2_plc(int addr, int value)
{
    if (g_plc_ok)
    {
        g_mutex.lock();
        int ret = modbus_write_bit(g_modbus, addr, value);
        g_mutex.unlock();
        //printf("modbus_write_bit:addr=%d,value=%d,ret=%d\n", addr, value, ret);
        return ret;
    }
    else {
        //std::cout << "PLC no ok" << std::endl;
        return false;
    }
}

int PLCDevice::read_bits_from_plc(int addr, int nb, uint8_t* value)
{
    if (g_plc_ok)
    {
        g_mutex.lock();
        int ret = modbus_read_bits(g_modbus, addr, nb, value);
        g_mutex.unlock();
        //printf("modbus_read_bits:addr=%d,nb=%d,value=%d,ret=%d\n", addr, nb, *value, ret);
        return ret;
    }
    else {
        //std::cout << "PLC no ok" << std::endl;
        return false;
    }
}

int PLCDevice::write_short_2_plc(int addr, int nb, uint16_t* value)
{
    if (g_plc_ok)
    {
        g_mutex.lock();
        int ret = modbus_write_registers(g_modbus, addr, nb, value);
        g_mutex.unlock();
        //printf("modbus_write_registers:addr=%d,nb=%d,value=%d,ret=%d\n", addr, nb, *value, ret);
        return ret;
    }
    else {
        //std::cout << "PLC no ok" << std::endl;
        return false;
    }
}

int PLCDevice::read_short_from_plc(int addr, int nb, uint16_t* value)
{
    if (g_plc_ok)
    {
        g_mutex.lock();
        int ret = modbus_read_registers(g_modbus, addr, nb, value);
        g_mutex.unlock();
        //printf("modbus_read_registers:addr=%d,nb=%d,value=%d,ret=%d\n", addr, nb, *value ,ret);
        return ret;
    }
    else {
        //std::cout << "PLC no ok" << std::endl;
        return false;
    }
}
