def create_current_config(org_id, asset_id): ''' Creates a consumable representation of an asset's current configuration. Merges the current configuration of a device with the list of all possible features to be configured for a device of its type. It then transorms this information into a structure useable by the templating engine. ''' #Get the asset's configuration and its device type's default configuration asset = fms_client.get_asset(asset_id) serial = asset.assetVO.deviceSerial device = device_client.get_device(org_id, serial=serial) type_ = device.deviceVO.deviceTypeVO.deviceTypeId deviceResponse = device_client.get_device_configuration(serial) defaultResponse = device_client.get_device_type_configuration(type_) #Combine the current configuration with the default one combined_dict = {} _update_combined( combined_dict, defaultResponse.deviceTypeConfigurationVO.featureVOs) if deviceResponse.deviceConfigurationVO is not None: # a device's config only exists if it's been configured previously _update_combined( combined_dict, deviceResponse.deviceConfigurationVO.featureVOs) #Create a data structure suitable for the template. Note that this # is specific to these applications and not especially important device_config_list = [] for feature_id, feature_name in combined_dict: feat = {'id': feature_id, 'name': feature_name, 'attrs': sorted(combined_dict[(feature_id, feature_name)].values(), key=lambda attr: attr.attrName) # sort by name } device_config_list.append(feat) return sorted(device_config_list, key=lambda element: element['name'])
def send_configuration(asset_id, config_data): ''' Overwrites the asset's configuration with the one given on the page. The page's form data is parsed and sanitized, then inserted in the appropriate places in the default configuration. This function sends every feature, but notice that this isn't necessary. If only one option is changed, only that feature needs to be sent back to the device. ''' #Get the device type's default configuration asset = fms_client.get_asset(asset_id) serial = asset.assetVO.deviceSerial device = device_client.get_device(asset.assetVO.organizationId, serial=serial) type_ = device.deviceVO.deviceTypeVO.deviceTypeId default = device_client.get_device_type_configuration(type_) # Set up default configuration details for quick access features = default.deviceTypeConfigurationVO.featureVOs feat_names = {f.featureId: f.featureName for f in features} default_attrs = {feature.featureId: {attribute.attrId: attribute for attribute in feature.attributeVOs} for feature in features} # Set up form data for insertion into default_attrs. Note that this is # specific to this application. new_configs = {} for (feat_attr, attr_value) in config_data: # This is where the strange form names come in handy feat_id, attr_id = [int(elem) for elem in feat_attr.split('_')] new_configs.setdefault(feat_id, {}) new_configs[feat_id][attr_id] = attr_value #Sanitize form data and insert back into the default configurations changed_features = [] for feat_id in new_configs: changed_features.append(feat_id) for attr_id in new_configs[feat_id]: attr_value = new_configs[feat_id][attr_id] if attr_value == 'on': attr_value = '1' if attr_value == '': attr_value = None default_attrs[feat_id][attr_id].attrValue = attr_value #Revert default_configs to a nested list structure configuration = [] for feat_id in changed_features: featureVO = device_client.create_feature(feat_id, feat_names[feat_id]) featureVO.attributeVOs = default_attrs[feat_id].values() configuration.append(featureVO) #Note that `configuration' is now in the correct data structure for sending # to MAP and the device. That is, configuration is a list of features, each # of which is a list of attributes. Each attribute has an attrName and an # attrValue field, as well as some secretarial fields like min, max, and ID response = device_client.update_configuration(serial, configuration) return {'code': response.code, 'message': response.message, }