diff --git a/CHANGES.md b/CHANGES.md
index 863df3e..319e5d4 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -5,6 +5,7 @@
in their terminal after installation, which will fire up the backend and
open the browser
- Add versioneer
+- Enable user to specify pump configuration directory
- Update to `react-scripts` 2.1.3
2018.11.07
diff --git a/pyqmix_backend/backend_app.py b/pyqmix_backend/backend_app.py
index ba821e5..42fad6e 100644
--- a/pyqmix_backend/backend_app.py
+++ b/pyqmix_backend/backend_app.py
@@ -112,7 +112,17 @@ class SetUpConfig(Resource):
def get(self):
# Return a list of available config-dirs and send to frontend
- list_of_available_configurations = config.get_available_qmix_configs()
+ try:
+ list_of_available_configurations = config.get_available_qmix_configs()
+ except:
+ list_of_available_configurations = [] # If the default configuration does not exist
+
+ if list_of_available_configurations:
+ configuration_path = config.DEFAULT_CONFIGS_DIR
+ else: # If the default configuration path does not exist or if there are no configurations
+ configuration_path = op.expanduser('~')
+ list_of_available_configurations = config.get_available_qmix_configs(configs_dir=configuration_path)
+
list_of_available_syringe_sizes = list(syringes.keys())
# Return status of pump-setup
@@ -120,7 +130,8 @@ def get(self):
setup_dict = {'is_config_set_up': config_setup,
'available_configs': list_of_available_configurations,
- 'available_syringes': list_of_available_syringe_sizes}
+ 'available_syringes': list_of_available_syringe_sizes,
+ 'configuration_path': configuration_path}
return setup_dict
@api.expect(config_setup)
@@ -132,6 +143,21 @@ def put(self):
set_up_config(config_name=config_name)
+@api.route('/api/config_update')
+class UpdateConfig(Resource):
+
+ def put(self):
+ payload = request.json
+ configuration_path = payload['configPath']
+ try:
+ list_of_available_configurations = config.get_available_qmix_configs(configs_dir=configuration_path)
+ except: # Return empty list if path does not exist
+ list_of_available_configurations = []
+ setup_dict = {'available_configs': list_of_available_configurations}
+
+ return setup_dict
+
+
@api.route('/api/pumps')
class InitiateOrDisconnectPumps(Resource):
@@ -268,6 +294,7 @@ def disconnect_pumps():
print(f'Bus after "closing": {session_paramters["bus"]}')
session_paramters['pumps'] = {}
+ config.delete_config()
return True
@@ -296,8 +323,8 @@ def get_pump_state(pump_id):
return pump_status
-def pump_set_fill_level(pump_id, target_volume, flow_rate):
+def pump_set_fill_level(pump_id, target_volume, flow_rate):
if app.config['test_session']:
print(f'Starting virtual pump: {pump_id} and setting '
f'target_volume to {target_volume} mL '
diff --git a/pyqmix_frontend/src/App.js b/pyqmix_frontend/src/App.js
index c177920..228738b 100644
--- a/pyqmix_frontend/src/App.js
+++ b/pyqmix_frontend/src/App.js
@@ -12,10 +12,11 @@ class PumpForm extends Component {
// System setup
webConnectedToPumps: false, // Does the website think the pumps are connected (based on user-input, not backend)
- isPumpConfigSetUp: false, // Are the pumps set up in the backend
+ isPumpConfigSetUp: false, // Are the pumps configured in the backend
userEnteredPumpConfiguration: false, // Method to wait for user input on config-name and pump-type
availableConfigurations: [],
availableSyringeTypes: [],
+ configurationPath: "",
selectedQmixConfig: "",
selectedSyringeType: "",
userEnteredBubbleToggle: "",
@@ -78,6 +79,10 @@ class PumpForm extends Component {
// --- Update state by Configuration and Syringe Size fields --- //
handleConfigNameChange = (e) => this.setState({selectedQmixConfig: e.target.innerText});
handleSyringeTypeChange = (e) => this.setState({selectedSyringeType: e.target.innerText});
+ handleConfigPathChange = (e) => {
+ this.setState({configurationPath: e.target.value});
+ this.updateAvailableConfigurations(e.target.value);
+ };
handleLocatingConfig = () => {
this.toggle('locateConfigFiles');
this.setState({userEnteredPumpConfiguration: true})
@@ -321,9 +326,12 @@ class PumpForm extends Component {
},
});
const json = await response.json();
- await this.asyncSetState({isPumpConfigSetUp: json['is_config_set_up']});
+ // Uncommented since I want to configure pumps every time I press 'Detect Pumps'
+ // await this.asyncSetState({isPumpConfigSetUp: json['is_config_set_up']});
+ await this.asyncSetState({isPumpConfigSetUp: false});
await this.asyncSetState({availableConfigurations: json['available_configs']});
await this.asyncSetState({availableSyringeTypes: json['available_syringes']});
+ await this.asyncSetState({configurationPath: json['configuration_path']});
// Use first item as default.
const defaultConfig = this.state.availableConfigurations[0];
@@ -332,6 +340,23 @@ class PumpForm extends Component {
await this.asyncSetState({selectedSyringeType: defaultSyringeType})
};
+ updateAvailableConfigurations = async (configPath) => {
+ let payload = {configPath: configPath};
+ const response = await fetch('/api/config_update', {
+ method: 'put',
+ headers: {
+ 'Accept': 'application/json, text/plain, */*',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify(payload)
+ });
+ const json = await response.json();
+ await this.asyncSetState({availableConfigurations: json['available_configs']});
+
+ const defaultConfig = this.state.availableConfigurations[0];
+ await this.asyncSetState({selectedQmixConfig: defaultConfig});
+ };
+
// --- Function to wait for user input --- //
waitForConfigFilesToBeSet = async () => {
do {
@@ -713,26 +738,47 @@ class PumpForm extends Component {
onSubmit={(e) => {
e.preventDefault();
}}>
- {/*Dropdown for config name*/}
-