Skip to content
seqIDataMgr.cpp 109 KiB
Newer Older
                             throw("Invalid Proxy");
                             // setting name of SASHA produced FITS in data manager component
                             status = archiver->setCurrentFilenameSASHA(filenameSASHA);
                             U4_LLOG(archiver->getCurrentFilenameSASHA());


                             // creating fits file with no data and with complete+populated header.
                             status = archiver->createEmptyAndPopulateHeader(filnameSHINS, bitpix, naxis, vecNaxes);
                             status = archiver->mergeHeadersAndCopyData(filenameSHINS, filenameSASHA);
                             */
                        }
                    }
                }

            }
        }
        if(dataMgrIC)dataMgrIC->destroy();

        // creating standard vectors with keywords values and comments for SHINS part of header.
        // These vectors will be passed to data manager which will merge them to SASHA header
        // by creating in place a FITS header and merging it to SASHA header, without creating
        // a second file on disk

        // create header only fits file to fill with SHINS values for keywords

        // try 
        // {
        //     dataMgrIC = Ice::initialize(argcDataMgr, argvDataMgr);
        //     Ice::ObjectPrx base = dataMgrIC->stringToProxy("dataManagerAdapter:default -p 10501");
        //     sd::fitsFilePrx archiver = sd::fitsFilePrx::checkedCast(base);
        //     if (!archiver)
        //         throw("Invalid Proxy");
        //     status = archiver->saveSASHABLOB(toBitsBlob, counter);
        //     status = archiver->setCurrentFilenameSASHA(_outFilenameSASHA);
        // } 
        // catch (const Ice::Exception& ex)
        // catch (const char* msg)
        // if (dataMgrIC)dataMgrIC->destroy();

        // timeOut = su::convertStringToType<long>(itDit->second)*
        //           su::convertStringToType<float>(itNDit->second)*std::pow(10,6); // time out have to be in micro seconds
        // U1_LLOG("time out = " << timeOut*2 << " micro seconds");
        // IndiProperty sashaSaveFileNum(IndiProperty::Text);
        // IndiProperty sharknirUTCDate(IndiProperty::Number);
        // the method shouhld check on remote INDI property for info on exposure status
        // alredy done by sashaExpose, but to control twice is better
        // _outFilenameSASHA = "No Filename Retrieved";
        // boost::thread fits_notify_thread(inotifierInstance.start, _remotePathToWatch,
        //                                  boost::ref(_outFilenameSASHA),
        //                                  timeOut*6); // create and start thread
        // fits_notify_thread.join();               // Wait for thread to finish
        // check on _outFilenameSASHA
        // fits_notify_thread should have timeout parameter for INotifier::start
        itFind = _dSashaSetup.find("OBJECTNAME");
        if (!(itFind == _dSashaSetup.end()))strObjname = itFind->second;

        // sashaSaveFileNum = init_indi_property("sasha_save", "largest_filenum", IndiProperty::Text, std::vector<std::string>(1, "value"));

        // vecElemNames.push_back("JD");
        // vecElemNames.push_back("UTC");
        // vecElemNames.push_back("UTCDate");
        // vecElemNames.push_back("LT");
        // vecElemNames.push_back("LST");
        // vecElemNames.push_back("MoonAz");
        // vecElemNames.push_back("MoonAlt");
        // vecElemNames.push_back("MoonElong");
        // vecElemNames.push_back("MoonLit");
        // vecElemNames.push_back("SunAz");
        // vecElemNames.push_back("SunAlt");
        // sharknirUTCDate = init_indi_property("sharknir_time", "Now",
        //                                      IndiProperty::Number,
        //                                      vecElemNames);
        // // NOTE while alive, indiserver does not close the connection to the client.

        // U1_LLOG("Asking INDI for file number ...");
        // m_ptrIc2->send_get_property_wait(sashaSaveFileNum, recvProp);
        // streamFileNum << std::setfill('0') << std::setw(6)
        //               << recvProp["value"].getValue() << std::setfill(' ');

        // recvProp.clear();
        // U1_LLOG("Asking INDI for UTC date ... ");
        // m_ptrIc2->send_get_property_wait(sharknirUTCDate, recvProp);
        // strUTCDate = recvProp["UTCDate"].getValue().substr(2,recvProp["UTCDate"].getValue().size()-2);
        // U1_LLOG("Got " << recvProp["UTCDate"].getValue());
        // U1_LLOG("Extracted " << strUTCDate);
        // streamRsync << "rsync -avzh " << su::get_LLOGin() << "@sashaws::fits/" << strUTCDate
        //             << "/sa_" << strUTCDate << "_" << streamFileNum.str()
        //             << ".fits " << dataDir
        //             << "SHARKNIR_" << strObjname << "_" << recvProp["UTCDate"].getValue()
        //             << "_" << streamFileNum.str() << ".fits";
        // streamFileName << "SHARKNIR_" << strObjname << "_" << recvProp["UTCDate"].getValue()
        //                << "_" << streamFileNum.str() << ".fits";

        // status = std::system(streamRsync.str().c_str());

    }
#endif
    U8_LLOG("");
    return status;
}


int SeqDataMgr::sashaSetup(const std::map<std::string, std::string> & _dSashaExpose)
{
    U6_LLOG(__FUNCTION__);
    int status = EXIT_SUCCESS;
    m_exposeMutex.lock();
    try
    {
        std::vector<std::string>allowed_setup;
        allowed_setup.push_back("InstrumentMode");
        allowed_setup.push_back("OBJECTNAME");
        allowed_setup.push_back("NGROUPS");
        allowed_setup.push_back("NREADS");
        allowed_setup.push_back("NDROPS");
        allowed_setup.push_back("NCOADDS");
        allowed_setup.push_back("NRESETS");
        allowed_setup.push_back("NDIT");
        allowed_setup.push_back("SAVE");
        allowed_setup.push_back("READOUT");
        std::map<std::string, std::string>::const_iterator itSetup;
        for(itSetup = _dSashaExpose.begin(); itSetup != _dSashaExpose.end(); itSetup++)
        {
            U9_LLOG("Keyword : " << itSetup->first << "; Value : " << itSetup->second);
            if(!(std::find(allowed_setup.begin(), allowed_setup.end(), itSetup->first) != allowed_setup.end()))
            {
                std::stringstream log_msg;
                log_msg << "Keyword not allowed in sashaExpose : " << itSetup->first;
                E_LLOG(log_msg.str());
                throw(std::invalid_argument(log_msg.str()));
            }
        }
        for(itSetup = _dSashaExpose.begin(); itSetup != _dSashaExpose.end(); itSetup++)
        {
            if(m_getFitsAbortFlag)break;
            if(itSetup->first == "InstrumentMode")
            {
                m_curInstMode = itSetup->second;
            }
            else
            {
    //            U9_LLOG("setup : " << itSetup->first << ":" << itSetup->second);
                IProperty & prop = m_sashaProps.find(itSetup->first)->second;
                const std::map<std::string, indi::IElement> elements = prop.getElements();
                bool bPropError = false, bSetProperty = false;
                if(itSetup->first == "SAVE")
                {
                    bool bSave = true;
                    su::get_bool_from_setup(_dSashaExpose,  "SAVE",  bSave);
                    std::map<std::string, indi::IElement>::const_iterator itEl;
                    for(itEl = elements.begin(); itEl != elements.end(); itEl++)
                    {
                        U9_LLOG("Elements: " << itEl->first);
                    }
                    if(elements.find("value") != elements.end())
                    {
                        indi::IElement::SwitchStateType switch_state = (bSave ? IElement::On : IElement::Off);
                        if(prop["value"].getSwitchState() != switch_state)
                        {
                            prop["value"].setSwitchState(switch_state);
                            U9_LLOG("Setting : " << "value" << " to " << bSave);
                    else
                        bPropError = true;
                }
                else if(itSetup->first == "OBJECTNAME")
                {
                    if(elements.find("value") != elements.end())
                    {
                        std::string current_name = prop["value"].getValue();
                        if(current_name != itSetup->second)
                        {
                            prop["value"].setValue(itSetup->second);
                            bSetProperty = true;
                        }
                    }
                    else
                        bPropError = true;
                }
    //            else if(itSetup->first == "NCOADDS")
    //            {
    //                if(elements.find("num_coadds") != elements.end())
    //                    prop["num_coadds"].setValue<int>(su::convertStringToType<int>(itSetup->second));
    //                else
    //                    bPropError = true;
    //            }
                else if(itSetup->first == "READOUT")
                {
                    if(elements.find("value") != elements.end())
                    {
                        if(prop["value"].getValue() != itSetup->second)
                        {
                            prop["value"].setValue(itSetup->second);
                            bSetProperty = true;
                        }
                    }
                    else
                        bPropError = true;
                }
                else
                {
                    if(elements.find("value") != elements.end())
                    {
//                        int value = su::convertStringToType<int>(prop["value"].getValue());
                        if(itSetup->second != prop["value"].getValue())
                        {
                            prop["value"].setValue<int>(su::convertStringToType<int>(itSetup->second));
                            bSetProperty = true;
                        }
                    }
                    else
                        bPropError = true;
                }
                if(bPropError)
                {
                    std::stringstream log_msg;
                    log_msg << "Error : IProperty \"" << prop.getDevice() << "." << prop.getName() << "\" from INDI Server has changed";
                    E_LLOG(log_msg.str());
                    throw(std::runtime_error(log_msg.str()));
                }
                else if(bSetProperty)
                {
                    m_sashaPropsSet[itSetup->first] = false;
                    SendNewProperty(prop);
                }
            }
        }
        bool wait_result = false;
        wait_result = WaitSetMessages(60000000);
        if(!wait_result)status = EXIT_FAILURE;
    }
    catch(...)
    {
        m_exposeMutex.unlock();
        U8_LLOG("");
        throw;
    }
    m_exposeMutex.unlock();
    U8_LLOG(__FUNCTION__ << " exiting");
    return status;
}


int SeqDataMgr::sashaSetFrequency(const std::map<std::string, std::string> & _dSashaExpose)
{
    U6_LLOG(__FUNCTION__);
    int status = EXIT_SUCCESS;
    m_exposeMutex.lock();
    try
    {
        std::map<std::string, std::string>::const_iterator itSetup;
        itSetup = _dSashaExpose.find("FREQUENCY");
        if(itSetup != _dSashaExpose.end())
        {
            IProperty & prop = m_sashaProps.find(itSetup->first)->second;
            const std::map<std::string, indi::IElement> elements = prop.getElements();
            if(elements.find("value") != elements.end())
            {
                if(prop["value"].getValue() != itSetup->second)
                {
                    prop["value"].setValue(itSetup->second);
                    m_sashaPropsSet[itSetup->first] = false;
                    SendNewProperty(prop);
                    //camera reinitializes and readout region is reset
                    m_sashaPropsSet["READOUT"] = false;
                    WaitSetMessages(60000000);
                }
            }
            else
            {
                U9_LLOG("Error: frequency property from INDI server has changed");
            }
        }
    }
    catch(...)
    {
        m_exposeMutex.unlock();
        U8_LLOG("");
        throw;
    }
    m_exposeMutex.unlock();
    U8_LLOG(__FUNCTION__ << " exiting");
    return status;
}


int SeqDataMgr::sashaExpose2(std::vector<std::string> & out_files)
{
    U6_LLOG(__FUNCTION__);
    int status = EXIT_SUCCESS;
    m_exposeMutex.lock();
    try
    {
        m_last_generated_files.clear();
        if(m_bSaveOnlyExposedFiles && !m_getFitsAbortFlag)
        {
            sashaBlob.setBLOBEnable(IProperty::Also);
            SendNewProperty(sashaBlob);
        }
        bool wait_result = false;
        wait_result = WaitSetMessages(60000000);
        if(!m_getFitsAbortFlag)
        {
            m_sashaPropsSet["EXPOSE"] = false;
            sashaExposeProp["value"].setSwitchState(IElement::On);
            SendNewProperty(sashaExposeProp);
            m_ExpectedBlobs = su::convertStringToType<int>(sashaNumSeqs["value"].getValue());
            wait_result = WaitSetMessages(30000000);
        }
        if(!m_getFitsAbortFlag)
        {
            wait_result = WaitStartAcquireOff(ExtimateTiming() + 20000);
            m_bBlobArrived = false;
        }
        if(m_bSaveOnlyExposedFiles)
        {
            if(m_ExpectedBlobs > 0)WaitBLOB(20000);
            sashaBlob.setBLOBEnable(IProperty::Never);
            SendNewProperty(sashaBlob);
        }
        if(!wait_result)status = EXIT_FAILURE;
        if(m_getFitsAbortFlag)
        {
            throw(std::runtime_error("Error acquisition aborted by user"));
        }
    }
    catch(...)
    {
        m_exposeMutex.unlock();
        if(m_getFitsAbortFlag)m_getFitsAbortFlag--;
        U8_LLOG("");
        throw;
    }
    if(m_getFitsAbortFlag)m_getFitsAbortFlag--;
    m_exposeMutex.unlock();
    out_files = m_last_generated_files;
    m_last_generated_file = "";
    m_last_generated_files.clear();
    U8_LLOG(__FUNCTION__ << " exiting");
    return status;
}


void SeqDataMgr::abortExposure()
{
    m_getFitsAbortFlag = 1;
    SendNewProperty(sashaStop);
}

bool SeqDataMgr::WaitSetMessages(int timeout)
{
    U6_LLOG(__FUNCTION__);
    bool wait_sets = true;
    int waited_time = 0;
    while(wait_sets)
    {
        usleep(200000);
        waited_time += 200000;
        std::map<std::string, bool>::iterator itSet;
        for(itSet = m_sashaPropsSet.begin(); itSet != m_sashaPropsSet.end(); itSet++)
        {
            if(!itSet->second)break;
        }
        wait_sets = itSet != m_sashaPropsSet.end();
        if(waited_time >= timeout)
        {
            std::stringstream log_msg;
            log_msg << __FUNCTION__ << " ~ Timed Out waiting for : ";
            for(itSet = m_sashaPropsSet.begin(); itSet != m_sashaPropsSet.end(); itSet++)
            {
                if(!itSet->second)
                    log_msg << itSet->first << " ~ ";
            }
            E_LLOG(log_msg.str());
        if(m_bReceivedEof)
        {
            E_LLOG("Received EOF");
            U8_LLOG("");
            throw(std::runtime_error("Indi Server signaled EoF"));
        }
        if(m_getFitsAbortFlag)break;
    }
    U8_LLOG(__FUNCTION__ << " ~ Exiting; waited " << waited_time/1000.f << "ms");
    return !wait_sets;
}

bool SeqDataMgr::WaitStartAcquireOff(unsigned int timeout)
{
    U6_LLOG(__FUNCTION__);
    bool wait_result = true;
    unsigned int waited_time = 0;
    while(wait_result)
    {
        usleep(200000);
        waited_time += 200;
        wait_result = !(sashaExposeProp["value"].getSwitchState() == IElement::Off);
        if(waited_time >= timeout)
        {
            E_LLOG(__FUNCTION__ << " ~ Timed Out");
            break;
        }
        if((waited_time % 300000) == 0)
        {
            U9_LLOG(__FUNCTION__ << " ~ Waiting " << waited_time/1000.f << "/" << timeout/1000.f << "s");
        }
        if(m_getFitsAbortFlag)break;
        if(m_bReceivedEof)
        {
            E_LLOG("Received EOF");
            U8_LLOG("");
            throw(std::runtime_error("Indi Server signaled EoF"));
        }
    }
    U8_LLOG(__FUNCTION__ << " ~ Exiting; waited " << waited_time << "ms");
    return !wait_result;
}

bool SeqDataMgr::WaitBLOB(unsigned int timeout)
{
    U6_LLOG(__FUNCTION__);
    bool wait_result = true;
    unsigned int waited_time = 0;
    while(wait_result)
    {
        usleep(200000);
        waited_time += 200;
        wait_result = !(m_bBlobArrived == true);
        if(wait_result && waited_time >= timeout)
        {
            E_LLOG(__FUNCTION__ << " ~ Timed Out");
            break;
        }
        if((waited_time % 300000) == 0)
        {
            U9_LLOG(__FUNCTION__ << " ~ Waiting " << waited_time/1000.f << "/" << timeout/1000.f << "s");
        }
        if(m_getFitsAbortFlag)break;
        if(m_bReceivedEof)
        {
            E_LLOG("Received EOF");
            U8_LLOG("");
            throw(std::runtime_error("Indi Server signaled EoF"));
        }
    }
    U8_LLOG(__FUNCTION__ << " ~ Exiting; waited " << waited_time << "ms");
    return !wait_result;
}
  // I_LOG("Asking for temperature to sensor");
  // IProperty sharknirTemp(IProperty::Text), recvProp;
  // sharknirTemp.setDevice("sharknir_temp");
  // sharknirTemp.setName("sensor");
  // sharknirTemp.add(IElement("enable_alarm"));
  // sharknirTemp.add(IElement("enable_collection"));
  // sharknirTemp.add(IElement("identifie"));
  // sharknirTemp.add(IElement("is_connected"));
  // sharknirTemp.add(IElement("max_value"));
  // sharknirTemp.add(IElement("min_value"));
  // sharknirTemp.add(IElement("notify_email_file"));
  // sharknirTemp.add(IElement("notify_email_list"));
  // sharknirTemp.add(IElement("tag"));
  // sharknirTemp.add(IElement("units"));
  // sharknirTemp.add(IElement("value"));
  // heater
  /*
  IProperty sharknirTempHeater(IndiProperty::Text);
  sharknirTempHeater.setDevice("sharknir_sensors");
  sharknirTempHeater.setName("Heater");
  sharknirTempHeater.setPerm(IndiProperty::ReadOnly);
  sharknirTempHeater.setState(IndiProperty::Busy);
  sharknirTempHeater.add(IndiElement("command"));
  sharknirTempHeater.add(IndiElement("enable_collection"));
  sharknirTempHeater.add(IndiElement("hardware_num"));
  sharknirTempHeater.add(IndiElement("identifier"));
  sharknirTempHeater.add(IndiElement("max_power"));
  sharknirTempHeater.add(IndiElement("power"));
  sharknirTempHeater.add(IndiElement("last_alarm"));
  sharknirTempHeater.add(IndiElement("max_value"));
  sharknirTempHeater.add(IndiElement("min_value"));
  sharknirTempHeater.add(IndiElement("resp_prefix_size"));
  sharknirTempHeater.add(IndiElement("setpoint"));
  sharknirTempHeater.add(IndiElement("simulation_value"));
  sharknirTempHeater.add(IndiElement("time"));
  sharknirTempHeater.add(IndiElement("units"));
  sharknirTempHeater.add(IndiElement("value"));
  */


void * SeqDataMgr::indi_client_thread(void * pMe)
{
    //usleep(15000000);
    while(System::isTimeToQuit() == false)
    {
        SeqDataMgr & Me = *((SeqDataMgr *)pMe);

        try
        {
            IBase::setupSocketFd(7624, "192.168.61.115");
            U9_LLOG("Connected to INDI Server");
            std::map<std::string, IProperty &>::iterator itProp;
            for(itProp = Me.m_sashaProps.begin(); itProp != Me.m_sashaProps.end(); itProp++)
            {
                itProp->second.clear();
            }
            Me.sashaBlob.setBLOBEnable(IProperty::Never);
            Me.sashaNumCoadds.add(IElement("value"));
            Me.sashaNumCoadds["value"].setValue<int>(1);
        }
        catch(...)
        {
            std::string what = boost::current_exception_diagnostic_information();
            std::string toErase = "std::exception::what :";
            size_t pos = what.find(toErase);
            if(pos != std::string::npos)what.erase(pos, toErase.length());
            what.erase(std::remove(what.begin(), what.end(), '\n'), what.end());
            std::stringstream log_msg;
            log_msg << "Error trying connection to INDI server : " << what;
            W_LLOG(log_msg.str());
            usleep(300000000);
            continue;
        }
        std::map<std::string, IProperty &>::iterator itProp;
        for(itProp = Me.m_sashaProps.begin(); itProp != Me.m_sashaProps.end(); itProp++)
        {
    //        U9_LLOG("Getting : " << it->second.getDevice() << "." << it->second.getName());
            IOut(IMessage::Get) << itProp->second << std::endl;
        }

        IIn indiIn;
        IMessage indiMsgReceive;
        IProperty ipRecv;
        std::vector<IProperty>::iterator itVec;
        while(Me.m_bReceivedEof == false)
        {
            if(Me.m_bFlagChanged)
            {
                Me.m_bFlagChanged = false;
                if(Me.m_bSaveOnlyExposedFiles)
                    Me.sashaBlob.setBLOBEnable(IProperty::Never);
                else
                    Me.sashaBlob.setBLOBEnable(IProperty::Also);
                IOut(IMessage::EnB) << Me.sashaBlob << std::endl;

            }
            if(!Me.m_newProperties.empty())
            {
                Me.m_newPropMutex.lock();
                while(!Me.m_newProperties.empty())
                {
                    itVec = Me.m_newProperties.begin();
                    if(itVec->getDevice() == "sasha_save" && itVec->getName() == "save_image")
                    {
                        U9_LLOG("save_image ~ Enable Sent");
                        IOut(IMessage::EnB) << *itVec << std::endl;
                    }
                    else
                    {
                        IOut(IMessage::New) << *itVec << std::endl;
                    }
                    Me.m_newProperties.erase(itVec);
                }
                Me.m_newPropMutex.unlock();
            }
            if(indiIn.isReady(200) == true)
            {
                indiIn >> indiMsgReceive;
                IProperty propReceive = indiMsgReceive.getProperty();
                switch(indiMsgReceive.getType())
                {
                case IMessage::Unknown :
                    U9_LLOG(__FUNCTION__ << " ~ Received an Unknown for : \"" << Me.full_property_string(propReceive) << "\"");
                    break;
                case IMessage::Def :
    //                U9_LLOG(__FUNCTION__ << " ~ Received a DEF for : \"" << Me.full_property_string(propReceive) << "\"");
                    Me.CheckUpdateProperty(propReceive);
                    break;
                case IMessage::Del :
                    U9_LLOG(__FUNCTION__ << " ~ Received a DEL for : \"" << Me.full_property_string(propReceive) << "\"");
                    break;
                case IMessage::EnB :
                    U9_LLOG(__FUNCTION__ << " ~ Received a ENB for : \"" << Me.full_property_string(propReceive) << "\"");
                    break;
                case IMessage::Eof :
                    U9_LLOG(__FUNCTION__ << " ~ Received an EOF for : \"" << Me.full_property_string(propReceive) << "\"");
                    break;
                case IMessage::Get :
                    U9_LLOG(__FUNCTION__ << " ~ Received a Get for : \"" << Me.full_property_string(propReceive) << "\"");
                    break;
                case IMessage::Msg :
                    U9_LLOG(__FUNCTION__ << " ~ Received a Msg for : \"" << Me.full_property_string(propReceive) << "\"");
                    break;
                case IMessage::New :
                    U9_LLOG(__FUNCTION__ << " ~ Received a NEW for : \"" << Me.full_property_string(propReceive) << "\"");
                    break;
                case IMessage::Set :
                    if(propReceive.getDevice() != "sharknir_temp" && propReceive.getName() != "sensor")
                    {
                        U9_LLOG(__FUNCTION__ << " ~ Received a SET for : \"" << Me.full_property_string(propReceive) << "\"");
                    }
                    Me.UpdateProperty(propReceive);
                    break;
                default:
                    E_LLOG(__FUNCTION__ << " ~ Unexpected INDI message (" << indiMsgReceive.getType() << ") : \"" << Me.full_property_string(propReceive) << "\"");
                    break;
                }
            }
        }
        usleep(60000000);
    }
    W_LLOG(__FUNCTION__ << " ~ Exiting");
    return NULL;
}

unsigned int SeqDataMgr::ExtimateTiming()
{
    int nreads, ngroups, ndrops, ncoadds, nresets, ndit;
    std::string readout = sashaReadout["value"].getValue();
    double frame_time = 4.5f;
    if(m_sashaTiming.find(readout) != m_sashaTiming.end())
        frame_time = m_sashaTiming[readout];
    nreads = su::convertStringToType<int>(sashaNumReads["value"].getValue());
    ngroups = su::convertStringToType<int>(sashaNumGroups["value"].getValue());
    ndrops = su::convertStringToType<int>(sashaNumDrops["value"].getValue());
    nresets = su::convertStringToType<int>(sashaNumResets["value"].getValue());
    ncoadds = su::convertStringToType<int>(sashaNumCoadds["value"].getValue());
    ndit = su::convertStringToType<int>(sashaNumSeqs["value"].getValue());
    unsigned int result = 1000*frame_time*ndit*(ngroups*(nreads + ndrops)*ncoadds - ndrops*ncoadds + nresets);
    U9_LLOG("ndit : " << ndit << "; nreads : " << nreads << "; ngroups : " << ngroups << "; ndrops : " << ndrops << "; ncoadds : " << ncoadds << "; nresets : " << nresets << "; frame time : " << frame_time << "; result = " << result);
    return result;
}

void SeqDataMgr::SendNewProperty(IProperty & prop)
{
    U9_LLOG(__FUNCTION__ << " ~ " << full_property_string(prop));
    m_newPropMutex.lock();
//    prop.setState(IProperty::Ok);
    m_newProperties.push_back(prop);
    m_newPropMutex.unlock();
}


void SeqDataMgr::UpdateProperty(const IProperty & prop)
{
    std::string device = prop.getDevice();
    std::string name = prop.getName();
    bool prop_updated = false;
    std::map<std::string, IProperty &>::iterator it;
    if(device == "sasha_save" && name == "save_image")
    {
        m_bBlobArrived = true;
        SaveIncomingFile(prop);
    }
    else
    {
        for(it = m_sashaProps.begin(); it != m_sashaProps.end(); it++)
        {
            if(device == it->second.getDevice())
            {
                if(name == it->second.getName())
                {
                    prop_updated = true;
                    if(prop.getDevice() == "sharknir_temp" && prop.getName() == "sensor")
                    {
                        if(prop.getElements().find("identifier") != prop.getElements().end())
                        {
                            if(prop["identifier"].get() != su::right(it->first, 1))continue;
                        }
                    }
                    it->second = prop;
                    m_sashaPropsSet[it->first] = true;
sharknirws2's avatar
sharknirws2 committed
                    // We do not log temperatures and pressure
                    if(prop.getDevice() != "sharknir_temp" && prop.getName() != "sensor" && prop.getDevice() != "sharknir_pres1" && prop.getName() != "sensor")
                    {
                        U9_LLOG("Property SET : " << prop.getDevice() << "." << prop.getName());
                    }
                }
            }
        }
        if(!prop_updated)
        {
            U9_LLOG("Unrecognized property " << prop.getDevice() << "." << prop.getName() << " received");
        }
    }
}


void SeqDataMgr::CheckUpdateProperty(const IProperty & prop)// DEF
{
    bool prop_updated = false;
    std::map<std::string, IProperty &>::iterator it;
    for(it = m_sashaProps.begin(); it != m_sashaProps.end(); it++)
    {
        if(prop.getDevice() == it->second.getDevice())
        {
            if(prop.getName() == it->second.getName())
            {
                prop_updated = true;
                if(it->second.getElements().empty())
                {
                    if(prop.getDevice() == "sharknir_temp" && prop.getName() == "sensor")
                    {
                        if(prop.getElements().find("identifier") != prop.getElements().end())
                        {
                            if(prop["identifier"].get() != su::right(it->first, 1))continue;
                        }
                    }
                    it->second = prop;
//                    it->second.setState(IProperty::Ok);
                    U9_LLOG("Property Initialized : " << full_property_string(prop));
                }
            }
        }
    }
    if(!prop_updated)
    {
        U9_LLOG("Unrecognized property " << prop.getDevice() << "." << prop.getName() << " received");
    }
}

std::string SeqDataMgr::full_property_string(const IProperty &prop)
{
    std::stringstream log_message;
    log_message << prop.createUniqueKey();
    log_message << " : ";
    std::map<std::string, indi::IElement>::const_iterator it;
    const std::map<std::string, indi::IElement> & elements = prop.getElements();
    switch(prop.getType())
    {
        case IProperty::Text:
        case IProperty::Number:
            for(it = elements.begin(); it != elements.end(); it++)
            {
                if(it->first != "file")
                {
                    log_message << "Element: '" << it->first << "'; Value : " << it->second.get() << "; ";
                }
                else
                {
                    log_message << "Element: '" << it->first << "'";
                }
            }
            break;
        case IProperty::Switch:
            for(it = elements.begin(); it != elements.end(); it++)
            {
                if(it->first == "value")
                {
                    bool isOn = it->second.getSwitchState() == IElement::On;
                    log_message << "Element: '" << it->first << "'; Value : IElement::" << (isOn ?  "On" : "Off") << "; ";
                }
                else
                {
                    log_message << "Element: '" << it->first << "'; Value : " << it->second.get() << "; ";
                }
            }
            break;
        case IProperty::Unknown:
            for(it = elements.begin(); it != elements.end(); it++)
            {
                log_message << "Unknown - Element: '" << it->first << "'; Value : " << it->second.get() << "; ";
            }
            break;
        case IProperty::Light:
            for(it = elements.begin(); it != elements.end(); it++)
            {
                log_message << "Ligth Type - Element: \"" << it->first << "\"; Value : \"" << it->second.get() << "\"; ";
            }
            break;
        case IProperty::BLOB:
            for(it = elements.begin(); it != elements.end(); it++)
            {
                log_message << "BLOB Type size : " << prop["file"].getSize<unsigned int>() << "; ";
            }
            break;
    }
//    else
    {
//        log_message << "EOF Message";
    }
    return log_message.str();
}

void * SeqDataMgr::fit_mem_realloc(void * old_pointer, size_t new_size)
{
    void * pNew = NULL;
    pNew = realloc(old_pointer, new_size);
    U9_LLOG(__FUNCTION__ << "  ~ " << old_pointer << " -> " << pNew << " ~ " << new_size/2880.f);
    return pNew;
}


int SeqDataMgr::UpdateFitFile(fitsfile * pInFit, fitsfile * ptrFits)
{
     char simple_test[84];
    *(simple_test + 80) = 0;
    char string_value[32];
    int ref_fit_status = 0;
    int update_fit_status = 0;
    int int_value;
    float float_value;
    fits_read_key(pInFit, TFLOAT,    "BZERO", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == KEY_NO_EXIST || ref_fit_status)
    {
        if(ref_fit_status != KEY_NO_EXIST)
        {
            U9_LLOG("ref_fit_status = " << ref_fit_status);
        }
        ref_fit_status = 0;
    }
    else
    {
        fits_update_key(ptrFits, TFLOAT,    "BZERO    ", &float_value, simple_test, &update_fit_status);
    }
    fits_read_key(pInFit, TFLOAT,    "BSCALE", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == KEY_NO_EXIST)
    {
        ref_fit_status = 0;
    }
    else
    {
        fits_update_key(ptrFits, TFLOAT,    "BSCALE   ", &float_value, simple_test, &update_fit_status);
    }
    fits_read_key(pInFit, TSTRING, "CAMERA", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "CAMERA", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "CAPCOMP", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "CAPCOMP", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "DATE-OBS", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "DTEOBSM", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "DETECTOR", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "DETECTOM", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "EXPMODE", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "EXPMODE", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "EXPTIME", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "EXPTIMEM", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "FILENAME", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "FILENAME", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "FILTPOLE", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "FILTPOLE", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "FRAME", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "FRAME", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "GAIN", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "GAINM", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "ITIME", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "ITIMEM", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "NCOADDS", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "NCOADDSM", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "NCOADDS", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "NDROPS", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "NDROPS", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "NGROUPS", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "NGROUPS", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "NOUTPUTS", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "NOUTPUTS", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "NRAMPS", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "NRAMPS", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "NREADS", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "NREADSM", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "NREADS", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "NRESETS", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "NRESETS", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "OBJNAME", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "OBJNAMEM", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "RAMPTIM", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "RAMPTIM", &float_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "SUBSECNM", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "SUBSECNM", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "SUBSECH  ", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "SUBSECH  ", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "SUBSECW  ", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "SUBSECW  ", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "SUBSECX1 ", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "SUBSECX1 ", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "SUBSECX2 ", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "SUBSECX2 ", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "SUBSECY1 ", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "SUBSECY1 ", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "SUBSECY2 ", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "SUBSECY2 ", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "SYSSWVER", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "SYSSWVER", &string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "TIME-END", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "TIME-END", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TSTRING, "TIME-OBS", string_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TSTRING, "TIME-OBS", string_value, simple_test, &update_fit_status);
    else ref_fit_status = 0;
    fits_read_key(pInFit, TFLOAT,  "USEREXP", &float_value, simple_test, &ref_fit_status);
    if(ref_fit_status == 0)fits_update_key(ptrFits, TFLOAT,  "USEREXP", &float_value, simple_test, &update_fit_status);

    if(update_fit_status)
    {
        U9_LLOG("Update Fit Status : " << update_fit_status);
        LogCfitsioStack(5);
    }
    return update_fit_status;
}

void SeqDataMgr::LogCfitsioStack(int n)
{
    char simple_test[84];
    *(simple_test + 80) = 0;
    for(int i = 0; i < 7; i++)
    {
        fits_read_errmsg(simple_test);
        U9_LLOG(simple_test);
    }

}

void SeqDataMgr::SaveIncomingFile(const IProperty & prop)
{
    U6_LLOG(__FUNCTION__);
    std::string filenameSASHA, filenameSHINS, dateISO8601;

    if(m_ExpectedBlobs > 0)m_ExpectedBlobs--;
    fitsfile * ptrFitsFileSASHA = NULL;
    fitsfile * ptrFitsFileSHINS = NULL;
    int FitsStatusShins = 0, FitsStatusSasha = 0;
//    std::vector<long> vecNaxes(4, 0);
    long naxes[4] = { 36, 40, 1, 1 };
    int bitpix = 16, naxis = 2;
    long naxesSasha[4] = { 36, 40, 1, 1 };
    int bitpixSasha = 16, naxisSasha = 4;
    char simple_test[84];
    *(simple_test + 80) = 0;
    if(prop.find("file"))
    {
        if(prop["file"].getSize<float>() > 0.0)
        {
            const char * fitsBytes = prop["file"].get().c_str();
            size_t blobSize = prop["file"].getSize<unsigned int>();
            void * pBlobIncoming = malloc(blobSize);
            if(pBlobIncoming)
            {
                int blobLength = from64tobits((char *)pBlobIncoming, fitsBytes);
                if(blobLength < 0)
                {
                    free(pBlobIncoming);
                    A_LLOG("Bad base 64 FITS file WILL NOT BE SAVED");
                }
                else
                {
                    dateISO8601 = prop.getTimeStamp().getFormattedIso8601Str();
                    su::SetTimeWorkingDirectory(dateISO8601);
                    filenameSHINS = "SHARKNIR." + dateISO8601 + "." + m_curInstMode + ".fits";
                    filenameSASHA = "SHARKNIR." + dateISO8601 + "." + m_curInstMode + ".SASHA.fits";
                    if(m_bSaveIncomingBlob)
                        su::debug_save_memory_block((char *)pBlobIncoming, blobSize, filenameSASHA.c_str());
                    fits_open_memfile(&ptrFitsFileSASHA, "", READONLY, &pBlobIncoming, &blobSize, 0, NULL, &FitsStatusSasha);
                    fits_get_img_param(ptrFitsFileSASHA, 4, &bitpixSasha, &naxisSasha, naxesSasha, &FitsStatusSasha);
                    if(FitsStatusSasha)LogCfitsioStack(5);

                    fits_create_file(&ptrFitsFileSHINS, filenameSHINS.c_str(), &FitsStatusShins);
                    fits_create_img(ptrFitsFileSHINS, bitpix, naxis, naxes, &FitsStatusShins);
                    FitsStatusShins = SetFitsValues(ptrFitsFileSHINS);
                    FitsStatusShins = UpdateFitFile(ptrFitsFileSASHA, ptrFitsFileSHINS);
                    fits_resize_img(ptrFitsFileSHINS, bitpixSasha, naxisSasha, naxesSasha, &FitsStatusShins);
                    fits_copy_data(ptrFitsFileSASHA, ptrFitsFileSHINS, &FitsStatusShins);
                    fits_write_chksum(ptrFitsFileSHINS, &FitsStatusShins);
                    fits_flush_file(ptrFitsFileSHINS, &FitsStatusShins);
                    if(FitsStatusShins)LogCfitsioStack(5);
                    FitsStatusShins = 0;
                    fits_close_file(ptrFitsFileSHINS, &FitsStatusShins);