public void visit(CyPhy.Component component) { Logger.WriteDebug("visit(CyPhy.Component): {0}", component.Path); var part = new MfgBom.Bom.Part(); // Check for a Property called "octopart_mpn" var octopart_mpn = component.Children.PropertyCollection.FirstOrDefault(p => p.Name == "octopart_mpn" && !String.IsNullOrWhiteSpace(p.Attributes.Value)); if (octopart_mpn != null) { part.octopart_mpn = octopart_mpn.Attributes.Value; } var instance = new MfgBom.Bom.ComponentInstance() { gme_object_id = component.ID, path = TrimPath(component.Path) }; part.AddInstance(instance); bom.AddPart(part); }
public void NoSuppliers() { var part = new MfgBom.Bom.Part(); part.AddInstance(new MfgBom.Bom.ComponentInstance()); part.SelectSupplier(1); Assert.Null(part.SelectedSupplierName); Assert.Null(part.SelectedSupplierPartCostPerUnit); Assert.Null(part.SelectedSupplierSku); }
public void NoSuppliers() { var part = new MfgBom.Bom.Part(); part.AddInstance(new MfgBom.Bom.ComponentInstance()); part.SelectSupplier(1); Assert.Null(part.SelectedSupplierName); Assert.Null(part.SelectedSupplierPartCostPerUnit); Assert.Null(part.SelectedSupplierSku); }
public void ExceedLimitAndRecover() { ExceedRateLimit(); var querier = new MfgBom.OctoPart.Querier(API_KEY); var part = new MfgBom.Bom.Part() { octopart_mpn = "SN74S74N" }; Assert.True(part.QueryOctopartData(API_KEY)); }
/// <summary> /// OctoPart query returns link to image of component. Download this image to the Windows temporary /// directory and invoke the Icon CAT module to store as part of the CyPhy component. /// </summary> public void AddOctoPartIconToComponent(CyPhy.Component comp, MfgBom.Bom.Part part) { if (!comp.Children.ResourceCollection.Any(r => r.Name == "Icon.png")) { //Download icon to temp directory WebClient webClient = new WebClient(); webClient.Headers.Add("user-agent", "meta-tools/" + VersionInfo.CyPhyML); String iconPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName().Replace(".", "") + ".png"); webClient.DownloadFile(part.Icon, iconPath); if (File.Exists(iconPath)) { // Invoke icon module CustomIconAdd iconModule = new CustomIconAdd(); iconModule.SetCurrentDesignElement(comp); iconModule.CurrentObj = CurrentObj; iconModule.AddCustomIcon(iconPath); // Relocate resource in component CyPhy.Resource resource = comp.Children.ResourceCollection.FirstOrDefault(r => r.Name == "Icon.png"); if (resource != null) { foreach (MgaPart item in (resource.Impl as MgaFCO).Parts) { item.SetGmeAttrs(null, RESOURCE_START_X, RESOURCE_START_Y + (resources_created * RESOURCE_ADJUST_Y)); } resources_created++; String iconPath_RelativeToProjRoot = Path.Combine(comp.GetDirectoryPath(ComponentLibraryManager.PathConvention.REL_TO_PROJ_ROOT), "icon.png"); comp.Preferences.Icon = iconPath_RelativeToProjRoot; } else { LogMessage(String.Format("Error creating icon resource for component {0}.", comp.Name), CyPhyGUIs.SmartLogger.MessageType_enum.Error); } // Delete icon from temp directory for cleanup File.Delete(iconPath); } else { LogMessage(String.Format("Error downloading icon from OctoPart for MPN {0}", part.octopart_mpn), CyPhyGUIs.SmartLogger.MessageType_enum.Error); } } else { LogMessage(String.Format("An icon is already specified for component {0}. Will not overwrite with OctoPart data.", comp.Name), CyPhyGUIs.SmartLogger.MessageType_enum.Warning); } }
/// <summary> /// OctoPart query returns link to datasheet of component. Download this file to the Windows temporary /// directory and invoke the Documentation CAT module to store as part of the CyPhy component. /// </summary> public void AddOctoPartDatasheetToComponent(CyPhy.Component comp, MfgBom.Bom.Part part) { if (!comp.Children.ResourceCollection.Any(r => r.Name == "Datasheet.pdf")) { //Download icon to temp directory WebClient webClient = new WebClient(); webClient.Headers.Add("user-agent", "meta-tools/" + VersionInfo.CyPhyML); String datasheetPath = Path.Combine(Path.GetTempPath(), "Datasheet.pdf"); webClient.DownloadFile(part.Datasheet, datasheetPath); if (File.Exists(datasheetPath)) { // Invoke icon module AddDocumentation docModule = new AddDocumentation(); docModule.SetCurrentDesignElement(comp); docModule.CurrentObj = CurrentObj; docModule.AddDocument(datasheetPath); // Relocate resource in component CyPhy.Resource resource = comp.Children.ResourceCollection.FirstOrDefault(r => r.Name.Contains("Datasheet")); if (resource != null) { foreach (MgaPart item in (resource.Impl as MgaFCO).Parts) { item.SetGmeAttrs(null, RESOURCE_START_X, RESOURCE_START_Y + (resources_created * RESOURCE_ADJUST_Y)); } resources_created++; } else { LogMessage(String.Format("Error creating datasheet resource for component {0}.", comp.Name), CyPhyGUIs.SmartLogger.MessageType_enum.Error); } // Delete icon from temp directory for cleanup File.Delete(datasheetPath); } else { LogMessage(String.Format("Error downloading icon from OctoPart for MPN {0}", part.octopart_mpn), CyPhyGUIs.SmartLogger.MessageType_enum.Error); } } else { LogMessage(String.Format("A datasheet is already specified for component {0}. ", comp.Name) + String.Format("Datasheet returned by OctoPart query is at: {0}. ", part.Datasheet) + "Will not overwrite with OctoPart data.", CyPhyGUIs.SmartLogger.MessageType_enum.Warning); } }
/// <summary> /// Creates a CyPhy property for each technical detail kept on file for an OctoPart component /// </summary> public void AddOctoPartTechSpecsToComponent(CyPhy.Component comp, MfgBom.Bom.Part part) { dynamic dynJson = Newtonsoft.Json.JsonConvert.DeserializeObject(part.TechnicalSpecifications); if (dynJson != null) { foreach (var spec in dynJson) { CyPhyClasses.Property.AttributesClass.DataType_enum type = DeterminePropertyDataType((string)spec.Value.metadata.datatype, (string)spec.Value.metadata.key); if (spec.Value.value.Count > 0) { BuildCyPhyProperty(comp, (string)spec.Value.metadata.key, (string)spec.Value.value[0], type, false); } // TODO: Add symbols if applicable ? // spec.metadata.unit // <-- returns null or {name, symbol} } #region layout // find the largest current X value so our new elements are added to the right of existing design elements // choose the greater value of PARAMETER_START_X and greatest_current_x, to handle case where models // have not yet been added (give user more space before the property list). greatest_current_x = 0; foreach (var child in GetCurrentDesignElement().AllChildren) { foreach (MgaPart item in (child.Impl as MgaFCO).Parts) { int read_x, read_y; string read_str; item.GetGmeAttrs(out read_str, out read_x, out read_y); greatest_current_x = (read_x > greatest_current_x) ? read_x : greatest_current_x; } } int PARAMETER_START = (PARAMETER_START_X > greatest_current_x) ? PARAMETER_START_X : greatest_current_x; int num_parsed_properties = 0; foreach (var property in comp.Children.PropertyCollection) { foreach (MgaPart item in (property.Impl as MgaFCO).Parts) { item.SetGmeAttrs(null, PARAMETER_START, PARAMETER_START_Y + (num_parsed_properties * PARAMETER_ADJUST_Y)); } num_parsed_properties++; } #endregion } }
/// <summary> /// Queries OctoPart for the category heirarchy with the category UID from OctoPart's website. /// The parent and all grandparent categories are stored and strung together to for the classification /// </summary> public void AddOctoPartClassificationToComponent(CyPhy.Component comp, MfgBom.Bom.Part part) { part.QueryCategory(part.CategoryUID); if (String.IsNullOrWhiteSpace(comp.Attributes.Classifications)) { comp.Attributes.Classifications = part.Classification; } else { LogMessage(String.Format("A classification is already specified for component {0}. ", comp.Name) + String.Format("Classification returned by OctoPart is {0}; will not overwrite.", part.Classification), CyPhyGUIs.SmartLogger.MessageType_enum.Warning); } }
public void QueryAndParse_ManyMPNs() { var listMpn = new List <String>() { "SN74S74N", "ERJ-2GE0R00X", "2-406549-1", "CRCW06031K00FKEA", "SMD100F-2", "TDGL002", "ATMEGA48-20AU" }; var dictFailures = new Dictionary <String, Exception>(); foreach (var mpn in listMpn) { var part = new MfgBom.Bom.Part() { octopart_mpn = mpn }; try { part.QueryOctopartData(); } catch (Exception ex) { dictFailures.Add(mpn, ex); } } if (dictFailures.Any()) { var msg = String.Format("Exception(s) encountered when processing {0} MPN(s):" + Environment.NewLine, dictFailures.Count); foreach (var kvp in dictFailures) { msg += kvp.Key + ": " + kvp.Value + Environment.NewLine + Environment.NewLine; } Assert.False(dictFailures.Any(), msg); } }
private static UserBomTableRow Convert(MfgBom.Bom.Part part) { return(new UserBomTableRow() { Description = part.Description, Manufacturer = part.Manufacturer, ManufacturerPartNumber = part.ManufacturerPartNumber, Notes = part.Notes, Package = part.Package, Quantity = part.quantity, ReferenceDesignators = String.Join(", " + Environment.NewLine, part.instances_in_design .Select(ci => ci.path)), Supplier1 = part.SelectedSupplierName, Supplier1PartNumber = part.SelectedSupplierSku, Supplier1UnitPrice = part.SelectedSupplierPartCostPerUnit }); }
public void NoUSDOffers() { var pathMockSellerMapStructure = Path.Combine(TEST_DIRECTORY, "MockDataStructures", "NoUSDOffers.SellerMapStructure.json"); var jsonMockSellerMapStructure = File.ReadAllText(pathMockSellerMapStructure); var part = new MfgBom.Bom.Part() { SellerMapStructure = JsonConvert.DeserializeObject <MfgBom.Bom.Part.SellerMapStruct>(jsonMockSellerMapStructure) }; part.AddInstance(new MfgBom.Bom.ComponentInstance()); part.SelectSupplier(1); Assert.Null(part.SelectedSupplierName); Assert.Null(part.SelectedSupplierPartCostPerUnit); Assert.Null(part.SelectedSupplierSku); }
private static void SelectFPGASupplier(int design_quantity, float expected_cost) { var pathMockSellerMapStructure = Path.Combine(TEST_DIRECTORY, "MockDataStructures", "LFE3-17EA-6MG328C.SellerMapStructure.json"); var jsonMockSellerMapStructure = File.ReadAllText(pathMockSellerMapStructure); var part = new MfgBom.Bom.Part() { SellerMapStructure = JsonConvert.DeserializeObject <MfgBom.Bom.Part.SellerMapStruct>(jsonMockSellerMapStructure) }; part.AddInstance(new MfgBom.Bom.ComponentInstance()); part.SelectSupplier(design_quantity); Assert.False(String.IsNullOrWhiteSpace(part.SelectedSupplierName)); Assert.Equal("Digi-Key", part.SelectedSupplierName); Assert.Equal(expected_cost, part.SelectedSupplierPartCostPerUnit); }
public void visit(CyPhy.Component component) { Logger.WriteDebug("visit(CyPhy.Component): {0}", component.Path); var part = new MfgBom.Bom.Part(); // Check for a Property called "octopart_mpn" var octopart_mpn = component.Children.PropertyCollection.FirstOrDefault(p => p.Name == "octopart_mpn" && !String.IsNullOrWhiteSpace(p.Attributes.Value)); if (octopart_mpn != null) { part.octopart_mpn = octopart_mpn.Attributes.Value; } var instance = new MfgBom.Bom.ComponentInstance() { gme_object_id = component.ID, path = TrimPath(component.Path) }; part.AddInstance(instance); bom.AddPart(part); }
public void NoUSDOffers() { var pathMockSellerMapStructure = Path.Combine(TEST_DIRECTORY, "MockDataStructures", "NoUSDOffers.SellerMapStructure.json"); var jsonMockSellerMapStructure = File.ReadAllText(pathMockSellerMapStructure); var part = new MfgBom.Bom.Part() { SellerMapStructure = JsonConvert.DeserializeObject<MfgBom.Bom.Part.SellerMapStruct>(jsonMockSellerMapStructure) }; part.AddInstance(new MfgBom.Bom.ComponentInstance()); part.SelectSupplier(1); Assert.Null(part.SelectedSupplierName); Assert.Null(part.SelectedSupplierPartCostPerUnit); Assert.Null(part.SelectedSupplierSku); }
public static void SelectSupplier(this MfgBom.Bom.Part part, int design_quantity) { // Initialize SelectedSupplier fields part.SelectedSupplierPartCostPerUnit = null; part.SelectedSupplierName = null; part.SelectedSupplierSku = null; if (part.SellerMapStructure == null || part.SellerMapStructure.sellerMap == null) { using (StringWriter sw = new StringWriter()) using (JsonTextWriter jtw = new JsonTextWriter(sw)) { Newtonsoft.Json.JsonSerializer.Create( new Newtonsoft.Json.JsonSerializerSettings() { Formatting = Newtonsoft.Json.Formatting.Indented, NullValueHandling = NullValueHandling.Ignore }) .Serialize(jtw, part); Console.Error.WriteLine("No sellers identified for part: " + Environment.NewLine + "{0}", sw.ToString()); return; } } int quantityNeeded = design_quantity * part.quantity; // Flatten the supplier structures for easier sorting List <FlatOffer> offers = new List <FlatOffer>(); foreach (var sellerToSku in part.SellerMapStructure.sellerMap) { foreach (var skuToCurrency in sellerToSku.Value.skuMap) { foreach (var currencyToPricePoint in skuToCurrency.Value.currencyMap) { foreach (var pricePoint in currencyToPricePoint.Value) { offers.Add(new FlatOffer() { supplier = sellerToSku.Key, sku = skuToCurrency.Key, currency = currencyToPricePoint.Key, quantity = pricePoint.quantity, price = pricePoint.price }); } } } } var offersUSD = offers.Where(o => o.currency == "USD"); if (false == offersUSD.Any()) { Console.WriteLine("Could not find any offers in USD for part with MPN {0}", part.octopart_mpn); return; } var offersByPrice = offersUSD.OrderBy(o => o.price); // Best offer is the cheapest one where we exceed its threshold. FlatOffer bestOffer = offersByPrice.FirstOrDefault(o => o.quantity <= quantityNeeded); if (bestOffer == null) { // Take lowest-quantity break. // If there's a tie in quantities, it will be the cheapest, since we're sorted by price. bestOffer = offersByPrice.OrderBy(o => o.quantity).First(); } part.SelectedSupplierPartCostPerUnit = bestOffer.price; part.SelectedSupplierName = bestOffer.supplier; part.SelectedSupplierSku = bestOffer.sku; }
public bool GetOctoPartData(CyPhy.Component component) { try { var part = new MfgBom.Bom.Part(); part.octopart_mpn = GetDeviceNameFromComponentEDAModel(component); if (string.IsNullOrWhiteSpace(part.octopart_mpn)) { return(false); } var desiredData = new List <string>() { "category_uids", "imagesets", "datasheets", "specs" }; part.QueryOctopartData(exact_only: true, includes: desiredData, grab_first: false); if (!part.valid_mpn) { LogMessage(String.Format("OctoPart MPN number {0} was not found in database", part.octopart_mpn), CyPhyGUIs.SmartLogger.MessageType_enum.Error); return(false); } if (part.too_broad_mpn) { LogMessage(String.Format("OctoPart MPN number {0} returned more than one possible match.", part.octopart_mpn), CyPhyGUIs.SmartLogger.MessageType_enum.Error); return(false); } // Add property for OctoPart MPN BuildCyPhyProperty(component, "octopart_mpn", part.octopart_mpn, CyPhyClasses.Property.AttributesClass.DataType_enum.String, false); // Add property for all details returned by specs if (String.IsNullOrWhiteSpace(part.TechnicalSpecifications)) { LogMessage(String.Format("No technical details provided for OctoPart MPN number {0}.", part.octopart_mpn), CyPhyGUIs.SmartLogger.MessageType_enum.Warning); } else { AddOctoPartTechSpecsToComponent(component, part); } // Add classification from category UIDs if (String.IsNullOrWhiteSpace(part.CategoryUID)) { LogMessage(String.Format("No Category UID/Classification for OctoPart MPN number {0}.", part.octopart_mpn), CyPhyGUIs.SmartLogger.MessageType_enum.Warning); } else { AddOctoPartClassificationToComponent(component, part); } // Add icon image (need to download) if (String.IsNullOrWhiteSpace(part.Icon)) { LogMessage(String.Format("No Icon was provided for OctoPart MPN number {0}.", part.octopart_mpn), CyPhyGUIs.SmartLogger.MessageType_enum.Warning); } else { AddOctoPartIconToComponent(component, part); } // Add datasheet documentation. if (String.IsNullOrWhiteSpace(part.Datasheet)) { LogMessage(String.Format("No datasheet was provided for OctoPart MPN number {0}.", part.octopart_mpn), CyPhyGUIs.SmartLogger.MessageType_enum.Warning); } else { AddOctoPartDatasheetToComponent(component, part); } LogMessage("OctoPart importer completed.", CyPhyGUIs.SmartLogger.MessageType_enum.Success); return(true); } catch (OctoPart.OctopartQueryException ex) { LogMessage("Error: " + ex.Message, CyPhyGUIs.SmartLogger.MessageType_enum.Error); return(false); } finally { clean_up(true); } }
public void QueryAndParse_ManyMPNs() { var listMpn = new List<String>() { "SN74S74N", "ERJ-2GE0R00X", "2-406549-1", "CRCW06031K00FKEA", "SMD100F-2", "TDGL002", "ATMEGA48-20AU" }; var dictFailures = new Dictionary<String, Exception>(); foreach (var mpn in listMpn) { var part = new MfgBom.Bom.Part() { octopart_mpn = mpn }; try { part.QueryOctopartData(); } catch (Exception ex) { dictFailures.Add(mpn, ex); } } if (dictFailures.Any()) { var msg = String.Format("Exception(s) encountered when processing {0} MPN(s):" + Environment.NewLine, dictFailures.Count); foreach (var kvp in dictFailures) { msg += kvp.Key + ": " + kvp.Value + Environment.NewLine + Environment.NewLine; } Assert.False(dictFailures.Any(), msg); } }
private static void SelectFPGASupplier(int design_quantity, float expected_cost) { var pathMockSellerMapStructure = Path.Combine(TEST_DIRECTORY, "MockDataStructures", "LFE3-17EA-6MG328C.SellerMapStructure.json"); var jsonMockSellerMapStructure = File.ReadAllText(pathMockSellerMapStructure); var part = new MfgBom.Bom.Part() { SellerMapStructure = JsonConvert.DeserializeObject<MfgBom.Bom.Part.SellerMapStruct>(jsonMockSellerMapStructure) }; part.AddInstance(new MfgBom.Bom.ComponentInstance()); part.SelectSupplier(design_quantity); Assert.False(String.IsNullOrWhiteSpace(part.SelectedSupplierName)); Assert.Equal("Digi-Key", part.SelectedSupplierName); Assert.Equal(expected_cost, part.SelectedSupplierPartCostPerUnit); }