Skip to content
Snippets Groups Projects
D22AutoConfig.cpp 7.09 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * Nomad Instrument Control Software
     *
     * Copyright 2011 Institut Laue-Langevin
     *
     * Licensed under the EUPL, Version 1.1 only (the "License");
     * You may not use this work except in compliance with the Licence.
     * You may obtain a copy of the Licence at:
     *
     * http://joinup.ec.europa.eu/software/page/eupl
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the Licence is distributed on an "AS IS" basis,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the Licence for the specific language governing permissions and
     * limitations under the Licence.
     */
    
    #include "controllers/common/family/Families.h"
    #include <boost/lexical_cast.hpp>
    #include <common/base/Date.h>
    #include <InstrumentManager/InstrumentManager.h>
    #include <controllers/common/acquisition/Count.h>
    #include <controllers/common/acquisition/detector/DetectorElement.h>
    #include "NumorMessages.pb.h"
    #include "D22AutoConfig.h"
    #include <fstream>
    #include <iostream>
    
    namespace d22 {
    
    using namespace std;
    using namespace common;
    using namespace boost;
    using namespace cameo;
    
    const std::string AutoConfig::TYPE = "d22_auto_config";
    const std::string AutoConfig::REMOTE_APPLICATION = "autoconfig";
    const std::string AutoConfig::RESPONDER = "responder";
    
    AutoConfig::AutoConfig(const std::string& name) :
    
    	ExperimentController(name), controller::Start(this), Apply(this),
    	m_countSpy(nullptr) {
    
    
    	setFamily(family::ACQUISITION, family::SETTING);
    
    	serverEndpoint.init(this, SAVE, "cameo_server");
    	initialized.init(this, NOSAVE, "initialized");
    
    
    	scatterModelType.init(this, NOSAVE, "scatter_model_type");
    	sampleRadius.init(this, NOSAVE, "sample_radius");
    
    	resultSize.init(this, NOSAVE, "result_size");
    	type.init(this, NOSAVE, "type");
    
    	distance.init(this, NOSAVE, "distance");
    	wavelength.init(this, NOSAVE, "wavelength");
    	collimation.init(this, NOSAVE, "collimation");
    
    
    	wantedType.init(this, NOSAVE, "wanted_type");
    
    	wantedType.setEnumeratedValues(type);
    	wantedType.setEnumeratedLabels(type);
    
    
    	m_d22settings.init(this, "settings");
    	m_driver.init(this, "driver");
    }
    
    AutoConfig::AutoConfig(const AutoConfig& controller) :
    
    	ExperimentController(controller), controller::Start(this), Apply(this),
    	m_countSpy(nullptr) {
    
    }
    
    AutoConfig::~AutoConfig() {
    
    	if (m_remoteApplication.get() != NULL) {
    		// Stop the remote application.
    		m_remoteApplication->stop();
    
    		// Wait for the termination
    		application::State state = m_remoteApplication->waitFor();
    
    		cout << "Remote application " << m_remoteApplication->getName() << " terminated with state " << application::toString(state) << endl;
    	}
    }
    
    void AutoConfig::postConfiguration() {
    
    	if (m_server.get() == nullptr) {
    		// Create a new server if it is not already created.
    		// In case of a simulated server, avoid the real remote endpoint.
    		if (serverEndpoint() == "" || m_driver->state() != REAL_DEVICE_CONTAINER) {
    			m_server.reset(new Server(application::This::getServer().getEndpoint()));
    		} else {
    			m_server.reset(new Server(serverEndpoint()));
    		}
    	}
    
    	// Get the count spy.
    	m_countSpy = dynamic_cast<utilities::CountSpy*>(InstrumentManager::getInstance()->getFirstExperimentControllerByType(utilities::CountSpy::TYPE));
    	if (m_countSpy != nullptr) {
    		m_countSpy->attach(this);
    	}
    
    	initialized = initApplication();
    }
    
    bool AutoConfig::initApplication() {
    
    	// Do not initialize if it is already done
    	if (initialized()) {
    		return true;
    	}
    
    	// Start the remote server
    	if (!m_server->isAvailable(1000)) {
    		cout << "Remote server is not available" << endl;
    		return false;
    	}
    
    	cout << "Remote server is connected" << endl;
    
    	m_remoteApplication = m_server->connect(REMOTE_APPLICATION);
    	if (m_remoteApplication->exists()) {
    		// The application exists from a previous server session
    		m_remoteApplication->kill();
    		application::State state = m_remoteApplication->waitFor();
    		cout << "Terminated remote application with state " << application::toString(state) << endl;
    	}
    
    	m_remoteApplication = m_server->start(REMOTE_APPLICATION);
    
    	if (!m_remoteApplication->exists()) {
    		cout << "No remote application" << endl;
    		return false;
    	}
    
    	// Application initialized
    	initialized = true;
    
    	return true;
    }
    
    void AutoConfig::start() {
    
    	if (!initApplication()) {
    		return;
    	}
    
    	// Create the requester
    	unique_ptr<application::Requester> requester = application::Requester::create(*m_remoteApplication, RESPONDER);
    
    	if (requester.get() == nullptr) {
    		cout << "requester error" << endl;
    		return;
    	}
    
    	// Start date.
    	Date begin;
    
    	// Prepare the request.
    	lssautoconfig::NumorRequest request;
    
    	// Set the request parameters.
    	request.set_instrumentname("D22");
    
    
    	// Change to real values in the future?
    	request.mutable_parameters()->set_distance(m_d22settings->detPosition.setpoint());
    	request.mutable_parameters()->set_wavelength(m_d22settings->wavelengthPosition.setpoint());
    	request.mutable_parameters()->set_collimation(m_d22settings->colSetupPosition.setpoint());
    
    
    	request.set_type(lssautoconfig::NumorRequest_Type::NumorRequest_Type_Background);
    
    	// Get the data from the active count controller.
    	acquisition::Count* count = nullptr;
    	try {
    		count = dynamic_cast<acquisition::Count*>(InstrumentManager::getInstance()->getExperimentController(m_countSpy->countControllerName()));
    	}
    	catch (InstrumentManager::ControllerNotFound& e) {
    		log(Level::s_Error) << name << " missing controller " << m_countSpy->countControllerName() << endlog;
    		commandStatus.setError();
    		commandProgression = 100;
    		return;
    	}
    
    	int32 xSize = count->masterDetector->xSize();
    	int32 ySize = count->masterDetector->ySize();
    
    	request.set_xsize(xSize);
    	request.set_ysize(ySize);
    
    	cout << "Data size " << xSize << " x " << ySize << endl;
    
    	int32* data = count->masterDetector->data();
    	request.set_data(string(reinterpret_cast<const char *>(data), sizeof(int32) * xSize * ySize));
    
    	// Send the request.
    	requester->sendBinary(request.SerializeAsString());
    
    	// Wait for the response from the server.
    	string response;
    	requester->receiveBinary(response);
    
    	// Print the duration.
    	Date end;
    	double ms = (end - begin).getMilliseconds();
    	cout << "Request processed in " << ms << " ms" << endl;
    
    	lssautoconfig::Response autoConfigResponse;
    	autoConfigResponse.ParseFromString(response);
    
    
    	int size = autoConfigResponse.results_size();
    	resultSize = size;
    
    	type.resize(size);
    	distance.resize(size);
    	wavelength.resize(size);
    	collimation.resize(size);
    
    	for (int i = 0; i < size; ++i) {
    		type.set(i, autoConfigResponse.results(i).type());
    		distance.set(i, autoConfigResponse.results(i).parameters().distance());
    		wavelength.set(i, autoConfigResponse.results(i).parameters().wavelength());
    		collimation.set(i, autoConfigResponse.results(i).parameters().collimation());
    	}
    
    
    	scatterModelType = autoConfigResponse.scattermodeltype();
    	sampleRadius = autoConfigResponse.sampleradius();
    
    
    }
    
    void AutoConfig::apply() {
    
    	int32 size = resultSize();
    	for (int i = 0; i < size; ++i) {
    		if (type.get(i) == wantedType()) {
    
    			m_d22settings->detPosition.setpoint = distance.get(i);
    			m_d22settings->wavelengthPosition.setpoint = wavelength.get(i);
    
    			m_d22settings->colSetupPosition.setpoint = collimation.get(i); // check with tolerance
    		}
    	}