//
// Created by zx on 2019/12/9.
//

#include "PlcData.h"
#include <string.h>

PlcData* PlcData::g_instance=0;

PlcData* PlcData::GetInstance(std::string ip)
{
    if(g_instance==0)
        g_instance=new PlcData(ip);
    return g_instance;

}
void PlcData::UpdateData(stateCode code,int id)
{
    const int length=1;
    int offset=id*length;
    short* data = (short*)malloc(sizeof(short));
    memset(data, 0, sizeof(short));
    switch(code){
        case stateCode::eOk:
            *data = (short)1;
            break;
        case stateCode::eOutOfPlace:
            *data = (short)2;
            break;
        case stateCode::eNoCar:
        default:
            *data = (short)0;
            break;
    }
//    printf("data: %d \n", *data);
    m_lock.lock();
    ////判断越界
    if(offset>=0 && offset+length<=MAX_REGIONS)
        memcpy(m_data+offset,data,length*sizeof(short));
    m_lock.unlock();
    free(data);
}

void PlcData::plcThread(PlcData* p){
    if(p == 0) return;
    if(p->p_plc == 0) return;
    while(!p->m_cond_exit.WaitFor(1)){
        // 显示雷达结果
        std::cout<<"result: [";
        for (int i = 0; i < MAX_REGIONS; ++i) {
            std::cout<<p->m_data[i]<<" ";
        }
        std::cout<<"]"<<std::endl;
        // 写plc
        if(p->p_plc->getConnection()){

            short temp = 0;
            for (int i = 0; i < ELE_FENCE_COUNT; ++i) {
                temp= *(p->m_data+i);
//                temp =HTON(temp);
                //printf("%d ---->%d\n",*(p->m_data+i), temp);
                p->p_plc->WriteShorts(ELE_FENCE_DB_NUM, ELE_FENCE_START_ADDR+i*ELE_FENCE_OFFSET, 1, &temp);
                usleep(50*1000);
            }
        }else{
            p->p_plc->disconnect();
            if(p->m_ip_str != ""){
                p->p_plc->connect(p->m_ip_str);
            }
        }
        usleep(p->m_send_interval_milli * 1000);
    }
}

PlcData::PlcData(std::string ip):
p_send_thread(0),
m_ip_str("")
{
    m_ip_str = ip;
    memset(m_data, 0, MAX_REGIONS* sizeof(short));
    p_plc = new S7PLC();
    if(ip!=""){
        p_plc->connect(ip);
    }
    m_cond_exit.Notify(false);
    p_send_thread = new std::thread(plcThread, this);
}

void PlcData::Release(){
    if(g_instance) {
        g_instance->m_cond_exit.Notify(true);
        if(g_instance->p_plc){
            g_instance->p_plc->disconnect();
            delete g_instance->p_plc;
        }
        delete g_instance;
        g_instance = 0;
    }
}