def update_monitors(self): with self._bs.monitor_lock: print "UPDATING SYNOPTIC MONITORS" self._bs.setParam(SYNOPTIC_PRE + SYNOPTIC_GET_DEFAULT, compress_and_hex(self.get_default_synoptic_xml())) names = convert_to_json(self.get_synoptic_list()) self._bs.setParam(SYNOPTIC_PRE + SYNOPTIC_NAMES, compress_and_hex(names)) self._bs.updatePVs()
def update_monitors(self): """ Writes new device screens data to PVs """ with self._bs.monitor_lock: print "UPDATING DEVICES MONITORS" self._bs.setParam(GET_SCHEMA, compress_and_hex(self.get_devices_schema())) self._bs.setParam(GET_SCREENS, compress_and_hex(self._data)) self._bs.updatePVs()
def _add_all_parameter_pvs(self): """ Add PVs for each beamline parameter in the reflectometry configuration to the server's PV database. """ param_info = {} for group in BeamlineParameterGroup: param_info[group] = [] align_info = [] for parameter in self._beamline.parameters.values(): try: param_info_record = self._add_parameter_pvs(parameter) if param_info_record is not None: for group in parameter.group_names: param_info[group].append(param_info_record) if parameter.define_current_value_as is not None: align_info_record = { "name": param_info_record["name"], "prepended_alias": param_info_record["prepended_alias"], "type": "align", "description": "" } align_info.append(align_info_record) except Exception as err: STATUS_MANAGER.update_error_log("Error adding PV for parameter {}: {}".format(parameter.name, err), err) STATUS_MANAGER.update_active_problems( ProblemInfo("Error adding parameter PV", parameter.name, Severity.MAJOR_ALARM)) for param_group in BeamlineParameterGroup: self._add_pv_with_fields(PARAM_INFO_LOOKUP[param_group], None, STANDARD_2048_CHAR_WF_FIELDS, BeamlineParameterGroup.description(param_group), None, value=compress_and_hex(json.dumps(param_info[param_group]))) self._add_pv_with_fields(ALIGN_INFO, None, STANDARD_2048_CHAR_WF_FIELDS, "All alignment pvs information", None, value=compress_and_hex(json.dumps(align_info)))
def update_monitors(self): with self._bs.monitor_lock: print "UPDATING CONFIG LIST MONITORS" # Set the available configs self._bs.setParam(BlockserverPVNames.CONFIGS, compress_and_hex(convert_to_json(self.get_configs()))) # Set the available comps self._bs.setParam(BlockserverPVNames.COMPS, compress_and_hex(convert_to_json(self.get_components()))) # Update them self._bs.updatePVs()
def handle_pv_read(self, pv): if pv == RUNCONTROL_GET_PV: js = convert_to_json(self.get_current_settings()) value = compress_and_hex(js) return value elif pv == RUNCONTROL_OUT_PV: js = convert_to_json(self.get_out_of_range_pvs()) value = compress_and_hex(js) return value return ""
def _create_standard_pvs(self): self._bs.add_string_pv_to_db(SYNOPTIC_PRE + SYNOPTIC_NAMES, 16000) self._bs.add_string_pv_to_db(SYNOPTIC_PRE + SYNOPTIC_GET_DEFAULT, 16000) self._bs.add_string_pv_to_db(SYNOPTIC_PRE + SYNOPTIC_BLANK + SYNOPTIC_GET, 16000) self._bs.add_string_pv_to_db(SYNOPTIC_PRE + SYNOPTIC_SET_DETAILS, 16000) self._bs.add_string_pv_to_db(SYNOPTIC_PRE + SYNOPTIC_DELETE, 16000) self._bs.add_string_pv_to_db(SYNOPTIC_PRE + SYNOPTIC_SCHEMA, 16000) # Set values for PVs that don't change self.update_pv_value(SYNOPTIC_PRE + SYNOPTIC_BLANK + SYNOPTIC_GET, compress_and_hex(self.get_blank_synoptic())) self.update_pv_value(SYNOPTIC_PRE + SYNOPTIC_SCHEMA, compress_and_hex(self.get_synoptic_schema()))
def update_blocks_monitors(self): """Updates the monitors for the blocks and groups, so the clients can see any changes. """ with self.monitor_lock: # Blocks bn = convert_to_json(self._active_configserver.get_blocknames()) self.setParam(BlockserverPVNames.BLOCKNAMES, compress_and_hex(bn)) # Groups # Update the PV, so that groupings are updated for any CA monitors grps = ConfigurationJsonConverter.groups_to_json(self._active_configserver.get_group_details()) self.setParam(BlockserverPVNames.GROUPS, compress_and_hex(grps)) # Update them self.updatePVs()
def test_when_devices_screens_file_does_not_exist_then_current_uses_blank_devices_data(self): # Arrange self.dm.initialise() # Assert self.assertTrue(len(self.file_io.files) == 0) self.assertEquals(self.bs.pvs[GET_SCREENS], compress_and_hex(self.dm.get_blank_devices()))
def update_get_details_monitors(self): """Updates the monitor for the active configuration, so the clients can see any changes. """ with self.monitor_lock: js = convert_to_json(self._active_configserver.get_config_details()) self.setParam(BlockserverPVNames.GET_CURR_CONFIG_DETAILS, compress_and_hex(js)) self.updatePVs()
def update_bumpstrip_availability(self): """Updates the monitor for the configurations, so the clients can see any changes. """ with self.monitor_lock: # set the available configs self.setParam(BlockserverPVNames.BUMPSTRIP_AVAILABLE, compress_and_hex(self.bumpstrip)) # Update them self.updatePVs()
def _update_component_dependencies_pv(self, name): # Updates PV with list of configs that depend on a component configs = [] if name in self._comp_dependencies.keys(): configs = self._comp_dependencies[name] if name in self._component_metas.keys(): # Check just in case component failed to load pv_name = BlockserverPVNames.get_dependencies_pv(self._component_metas[name].pv) self._update_pv_value(pv_name, compress_and_hex(json.dumps(configs)))
def encode4return(self, data): """Converts data to JSON, compresses it and converts it to hex. Args: data (string): The data to encode Returns: string : The encoded data """ return compress_and_hex(json.dumps(data).encode('ascii', 'replace'))
def update_server_status(self, status=""): """Updates the monitor for the server status, so the clients can see any changes. Args: status (string): The status to set """ if self._active_configserver is not None: d = dict() d['status'] = status with self.monitor_lock: self.setParam(BlockserverPVNames.SERVER_STATUS, compress_and_hex(convert_to_json(d))) self.updatePVs()
def read(self, reason): """Overrides the read method of the pcaspy Driver class. Args: reason (string): The PV name. Returns: The PV value. """ if reason == 'CS:BLOCKSERVER:BLOCKVALUES': ans = convert_to_json(self._get_organised_values()) value = compress_and_hex(ans) else: value = self.getParam(reason) return value
def _create_pv(self, data): """Creates a single PV based on a name and data. Adds this PV to the dictionary returned on get_synoptic_list Args: data (string): Starting data for the pv, the pv name is derived from the name tag of this """ name = self._get_synoptic_name_from_xml(data) if name not in self._synoptic_pvs: # Extra check, if a non-case sensitive match exist remove it for key in self._synoptic_pvs.keys(): if name.lower() == key.lower(): self._synoptic_pvs.pop(key) pv = create_pv_name(name, self._synoptic_pvs.values(), "SYNOPTIC") self._synoptic_pvs[name] = pv # Create the PV self._bs.add_string_pv_to_db(SYNOPTIC_PRE + self._synoptic_pvs[name] + SYNOPTIC_GET, 16000) # Update the value self.update_pv_value(SYNOPTIC_PRE + self._synoptic_pvs[name] + SYNOPTIC_GET, compress_and_hex(data))
def _add_constants_pvs(self): """ Add pvs for the beamline constants """ beamline_constant_info = [] for beamline_constant in self._beamline.beamline_constants: try: const_alias = create_pv_name(beamline_constant.name, list(self.PVDB.keys()), CONST_PREFIX, limit=20, allow_colon=True) prepended_alias = "{}:{}".format(CONST_PREFIX, const_alias) if isinstance(beamline_constant.value, bool): value = 1 if bool(beamline_constant.value) else 0 fields = PARAM_FIELDS_BINARY elif isinstance(beamline_constant.value, str): value = beamline_constant.value fields = STANDARD_2048_CHAR_WF_FIELDS else: value = float(beamline_constant.value) fields = STANDARD_FLOAT_PV_FIELDS self._add_pv_with_fields(prepended_alias, None, fields, beamline_constant.description, None, interest="MEDIUM", value=value) logger.info("Adding Constant {} with value {}".format(beamline_constant.name, beamline_constant.value)) beamline_constant_info.append( {"name": beamline_constant.name, "prepended_alias": prepended_alias, "type": "float_value", "description": beamline_constant.description}) except Exception as err: STATUS_MANAGER.update_error_log("Error adding constant {}: {}".format(beamline_constant.name, err), err) STATUS_MANAGER.update_active_problems( ProblemInfo("Error adding PV for beamline constant", beamline_constant.name, Severity.MAJOR_ALARM)) self._add_pv_with_fields(BEAMLINE_CONSTANT_INFO, None, STANDARD_2048_CHAR_WF_FIELDS, "All value parameters", None, value=compress_and_hex(json.dumps(beamline_constant_info)))
def _add_all_driver_pvs(self): """ Add all pvs for the drivers. """ self.drivers_pv = {} driver_info = [] for driver in self._beamline.drivers: if driver.has_engineering_correction: correction_alias = create_pv_name(driver.name, list(self.PVDB.keys()), "COR", limit=12, allow_colon=True) prepended_alias = "{}:{}".format("COR", correction_alias) self._add_pv_with_fields(prepended_alias, None, STANDARD_FLOAT_PV_FIELDS, "Engineering Correction", None, archive=True) self._add_pv_with_fields("{}:DESC".format(prepended_alias), None, STANDARD_2048_CHAR_WF_FIELDS, "Engineering Correction Full Description", None) self.drivers_pv[driver] = prepended_alias driver_info.append({"name": driver.name, "prepended_alias": prepended_alias}) self._add_pv_with_fields(DRIVER_INFO, None, STANDARD_2048_CHAR_WF_FIELDS, "All corrections information", None, value=compress_and_hex(json.dumps(driver_info)))
def write(self, reason, value): """A method called by SimpleServer when a PV is written to the DatabaseServer over Channel Access. Args: reason (string): The PV that is being requested (without the PV prefix) value (string): The data being written to the 'reason' PV Returns: bool : True """ status = True try: if reason == 'ED:RBNUMBER:SP': #print_and_log("Updating to use experiment ID: " + value, "INFO", "DBSVR") self._ed.updateExperimentID(value) elif reason == 'ED:USERNAME:SP': self._ed.updateUsername(dehex_and_decompress(value)) except Exception as err: value = compress_and_hex(convert_to_json("Error: " + str(err))) print_and_log(str(err), "MAJOR") # store the values if status: self.setParam(reason, value) return status
def read(self, reason): """A method called by SimpleServer when a PV is read from the BlockServer over Channel Access. Args: reason (string): The PV that is being requested (without the PV prefix) Returns: string : A compressed and hexed JSON formatted string that gives the desired information based on reason. If an Exception is thrown in the reading of the information this is returned in compressed and hexed JSON. """ try: if reason == BlockserverPVNames.GROUPS: grps = ConfigurationJsonConverter.groups_to_json(self._active_configserver.get_group_details()) value = compress_and_hex(grps) elif reason == BlockserverPVNames.CONFIGS: value = compress_and_hex(convert_to_json(self._config_list.get_configs())) elif reason == BlockserverPVNames.COMPS: value = compress_and_hex(convert_to_json(self._config_list.get_components())) elif reason == BlockserverPVNames.BLANK_CONFIG: js = convert_to_json(self.get_blank_config()) value = compress_and_hex(js) elif reason == BlockserverPVNames.BUMPSTRIP_AVAILABLE: value = compress_and_hex(self.bumpstrip) elif reason == BlockserverPVNames.BANNER_DESCRIPTION: value = compress_and_hex(self.banner.get_description()) else: # Check to see if it is a on-the-fly PV for handler in self.on_the_fly_handlers: if handler.read_pv_exists(reason): return handler.handle_pv_read(reason) value = self.getParam(reason) except Exception as err: value = compress_and_hex(convert_to_json("Error: " + str(err))) print_and_log(str(err), "MAJOR") return value
def _create_pv(self): self._bs.add_string_pv_to_db(BlockserverPVNames.CONF_DESC_RULES, 16000) self._bs.setParam(BlockserverPVNames.CONF_DESC_RULES, compress_and_hex(json.dumps(self.rules))) self._bs.updatePVs()
def write(self, reason, value): """A method called by SimpleServer when a PV is written to the BlockServer over Channel Access. The write commands are queued as Channel Access is single-threaded. Note that the filewatcher is disabled as part of the write queue so any operations that intend to modify files should use the write queue. Args: reason (string): The PV that is being requested (without the PV prefix) value (string): The data being written to the 'reason' PV Returns: string : "OK" in compressed and hexed JSON if function succeeds. Otherwise returns the Exception in compressed and hexed JSON. """ status = True try: data = dehex_and_decompress(value).strip('"') if reason == BlockserverPVNames.LOAD_CONFIG: with self.write_lock: self.write_queue.append((self.load_config, (data,), "LOADING_CONFIG")) elif reason == BlockserverPVNames.SAVE_CONFIG: with self.write_lock: self.write_queue.append((self.save_active_config, (data,), "SAVING_CONFIG")) elif reason == BlockserverPVNames.RELOAD_CURRENT_CONFIG: with self.write_lock: self.write_queue.append((self.reload_current_config, (), "RELOAD_CURRENT_CONFIG")) elif reason == BlockserverPVNames.START_IOCS: with self.write_lock: self.write_queue.append((self.start_iocs, (convert_from_json(data),), "START_IOCS")) elif reason == BlockserverPVNames.STOP_IOCS: with self.write_lock: self.write_queue.append((self._ioc_control.stop_iocs, (convert_from_json(data),), "STOP_IOCS")) elif reason == BlockserverPVNames.RESTART_IOCS: with self.write_lock: self.write_queue.append((self._ioc_control.restart_iocs, (convert_from_json(data), True), "RESTART_IOCS")) elif reason == BlockserverPVNames.SET_CURR_CONFIG_DETAILS: with self.write_lock: self.write_queue.append((self._set_curr_config, (convert_from_json(data),), "SETTING_CONFIG")) elif reason == BlockserverPVNames.SAVE_NEW_CONFIG: with self.write_lock: self.write_queue.append((self.save_inactive_config, (data,), "SAVING_NEW_CONFIG")) elif reason == BlockserverPVNames.SAVE_NEW_COMPONENT: with self.write_lock: self.write_queue.append((self.save_inactive_config, (data, True), "SAVING_NEW_COMP")) elif reason == BlockserverPVNames.DELETE_CONFIGS: with self.write_lock: self.write_queue.append((self._config_list.delete, (convert_from_json(data),), "DELETE_CONFIGS")) elif reason == BlockserverPVNames.DELETE_COMPONENTS: with self.write_lock: self.write_queue.append((self._config_list.delete, (convert_from_json(data), True), "DELETE_COMPONENTS")) elif reason == BlockserverPVNames.BUMPSTRIP_AVAILABLE_SP: self.bumpstrip = data with self.write_lock: self.write_queue.append((self.update_bumpstrip_availability, None, "UPDATE_BUMPSTRIP")) else: status = False # Check to see if it is a on-the-fly PV for h in self.on_the_fly_handlers: if h.write_pv_exists(reason): with self.write_lock: self.write_queue.append((h.handle_pv_write, (reason, data), "SETTING_CONFIG")) status = True break except Exception as err: value = compress_and_hex(convert_to_json("Error: " + str(err))) print_and_log(str(err), "MAJOR") else: if status: value = compress_and_hex(convert_to_json("OK")) # store the values if status: self.setParam(reason, value) return status
def put_and_decode_ans(pv, value): caput(pv, compress_and_hex(value), wait=True) raw = caget(pv, True) js = dehex_and_decompress(raw) ans = json.loads(js) return ans
def _update_component_pv(self, name, data): # Updates pvs with new data pv_name = BlockserverPVNames.get_component_details_pv(self._component_metas[name].pv) self._update_pv_value(pv_name, compress_and_hex(json.dumps(data)))
def update(self, xml_data): """Updates the synoptic list when modifications are made via the filesystem. Args: xml_data (string): The xml data to update the PV with """ name = self._get_synoptic_name_from_xml(xml_data) self._add_to_version_control(name, "%s modified on filesystem" % name) names = self._synoptic_pvs.keys() if name in names: self.update_pv_value(SYNOPTIC_PRE + self._synoptic_pvs[name] + SYNOPTIC_GET, compress_and_hex(xml_data)) else: self._create_pv(xml_data) self.update_monitors()