Compare commits
7 Commits
ecb3ec0838
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 617de2e854 | |||
| a308b7982b | |||
| 955fbc5539 | |||
| 72cdb32750 | |||
| a0c707583d | |||
| 9088af52de | |||
| c5be48a807 |
@@ -0,0 +1,228 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using PepApi.Core.Models;
|
||||
using PepLib.Data;
|
||||
|
||||
namespace PepApi.Core.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("drawings")]
|
||||
public class DrawingsController : ControllerBase
|
||||
{
|
||||
private readonly PepDB _db;
|
||||
|
||||
public DrawingsController(PepDB db)
|
||||
{
|
||||
_db = db;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a list of drawings with optional filtering.
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<List<DrawingSummary>>> GetDrawings([FromQuery] DrawingFilterData? filter)
|
||||
{
|
||||
var drawings = await _db.Drawings
|
||||
.Select(d => new DrawingSummary
|
||||
{
|
||||
ID = d.ID,
|
||||
Name = d.Name,
|
||||
Customer = d.Customer,
|
||||
CustID = d.CustID,
|
||||
Revision = d.Revision,
|
||||
Description = d.Description,
|
||||
Material = d.Material,
|
||||
MaterialGrade = d.MatGrade,
|
||||
Status = d.Status,
|
||||
Type = d.Type,
|
||||
Application = d.Application,
|
||||
Programmer = d.Programmer,
|
||||
CreatedBy = d.CreatedBy,
|
||||
Width = d.Width,
|
||||
Length = d.Length,
|
||||
TrueArea = d.TrueArea,
|
||||
CutLength = d.CutLength,
|
||||
CreationDate = d.CreationDate,
|
||||
LastEditDate = d.LastEditDate,
|
||||
ModifiedDate = d.ModifiedDate,
|
||||
HasBevel = d.HasBevel != 0,
|
||||
HasLeadIn = d.HasLeadIn != 0,
|
||||
HasTab = d.HasTab != 0
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
if (filter != null)
|
||||
{
|
||||
var filtered = filter.Apply(drawings.AsQueryable()).ToList();
|
||||
var paginated = filtered.Skip(filter.Offset).Take(filter.Limit).ToList();
|
||||
return Ok(paginated);
|
||||
}
|
||||
|
||||
return Ok(drawings.Take(100).ToList());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a drawing by ID.
|
||||
/// </summary>
|
||||
[HttpGet("{id:int}")]
|
||||
public async Task<ActionResult<DrawingDetails>> GetDrawingById(int id)
|
||||
{
|
||||
var drawing = await _db.Drawings
|
||||
.Where(d => d.ID == id)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (drawing == null)
|
||||
return NotFound(new { message = "Drawing not found" });
|
||||
|
||||
return Ok(ConvertToDetails(drawing));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a drawing by exact name.
|
||||
/// </summary>
|
||||
[HttpGet("name/{name}")]
|
||||
public async Task<ActionResult<DrawingDetails>> GetDrawingByName(string name)
|
||||
{
|
||||
var drawing = await _db.Drawings
|
||||
.Where(d => d.Name.ToUpper() == name.ToUpper())
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (drawing == null)
|
||||
return NotFound(new { message = "Drawing not found" });
|
||||
|
||||
return Ok(ConvertToDetails(drawing));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search drawings by partial name.
|
||||
/// </summary>
|
||||
[HttpGet("search")]
|
||||
public async Task<ActionResult<DrawingSearchResponse>> SearchDrawings(
|
||||
[FromQuery] string search,
|
||||
[FromQuery] int limit = 100)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(search))
|
||||
return BadRequest(new { message = "Search term is required" });
|
||||
|
||||
var searchUpper = search.Trim().ToUpper();
|
||||
|
||||
var allMatches = await _db.Drawings
|
||||
.Where(d => d.Name.ToUpper().Contains(searchUpper))
|
||||
.Select(d => new DrawingSummary
|
||||
{
|
||||
ID = d.ID,
|
||||
Name = d.Name,
|
||||
Customer = d.Customer,
|
||||
CustID = d.CustID,
|
||||
Revision = d.Revision,
|
||||
Description = d.Description,
|
||||
Material = d.Material,
|
||||
MaterialGrade = d.MatGrade,
|
||||
Status = d.Status,
|
||||
Type = d.Type,
|
||||
Application = d.Application,
|
||||
Programmer = d.Programmer,
|
||||
CreatedBy = d.CreatedBy,
|
||||
Width = d.Width,
|
||||
Length = d.Length,
|
||||
TrueArea = d.TrueArea,
|
||||
CutLength = d.CutLength,
|
||||
CreationDate = d.CreationDate,
|
||||
LastEditDate = d.LastEditDate,
|
||||
ModifiedDate = d.ModifiedDate,
|
||||
HasBevel = d.HasBevel != 0,
|
||||
HasLeadIn = d.HasLeadIn != 0,
|
||||
HasTab = d.HasTab != 0
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
var limitedResults = limit > 0 ? allMatches.Take(limit).ToList() : allMatches;
|
||||
|
||||
return Ok(new DrawingSearchResponse
|
||||
{
|
||||
SearchTerm = search,
|
||||
TotalMatches = allMatches.Count,
|
||||
ResultsReturned = limitedResults.Count,
|
||||
Results = limitedResults
|
||||
});
|
||||
}
|
||||
|
||||
private static DrawingDetails ConvertToDetails(Drawing drawing)
|
||||
{
|
||||
return new DrawingDetails
|
||||
{
|
||||
ID = drawing.ID,
|
||||
Name = drawing.Name,
|
||||
CustID = drawing.CustID,
|
||||
Revision = drawing.Revision,
|
||||
Path = drawing.Path,
|
||||
File = drawing.File,
|
||||
InUseBy = drawing.InUseBy,
|
||||
InUseDate = drawing.InUseDate,
|
||||
Status = drawing.Status,
|
||||
StatusModifiedBy = drawing.StatusModifiedBy,
|
||||
StatusModifiedDate = drawing.StatusModifiedDate,
|
||||
CreationDate = drawing.CreationDate,
|
||||
LastEditDate = drawing.LastEditDate,
|
||||
LastRefDate = drawing.LastRefDate,
|
||||
Description = drawing.Description,
|
||||
Customer = drawing.Customer,
|
||||
Comment = drawing.Comment,
|
||||
Notes = drawing.Notes,
|
||||
Grain = drawing.Grain,
|
||||
GrainAngle = drawing.GrainAngle,
|
||||
Material = drawing.Material,
|
||||
MaterialGrade = drawing.MatGrade,
|
||||
Programmer = drawing.Programmer,
|
||||
CreatedBy = drawing.CreatedBy,
|
||||
Type = drawing.Type,
|
||||
CommonCut = drawing.CommonCut,
|
||||
CombineCut = drawing.CombineCut,
|
||||
Errors = drawing.Errors,
|
||||
Hardness = drawing.Hardness,
|
||||
Specification = drawing.Specification,
|
||||
NestInCutOuts = drawing.NestInCutOuts,
|
||||
UserDefined1 = drawing.UserDefined1,
|
||||
UserDefined2 = drawing.UserDefined2,
|
||||
UserDefined3 = drawing.UserDefined3,
|
||||
UserDefined4 = drawing.UserDefined4,
|
||||
UserDefined5 = drawing.UserDefined5,
|
||||
UserDefined6 = drawing.UserDefined6,
|
||||
Machine = drawing.Machine,
|
||||
Application = drawing.Application,
|
||||
PartCount = drawing.PartCount,
|
||||
Color = drawing.Color,
|
||||
CombineMethod = drawing.CombineMethod,
|
||||
SeqCutouts = drawing.SeqCutouts,
|
||||
AllowMirror = drawing.AllowMirror,
|
||||
SourceFile = drawing.SourceFile,
|
||||
SourceDate = drawing.SourceDate,
|
||||
SourceSize = drawing.SourceSize,
|
||||
CadScaled = drawing.CadScaled,
|
||||
CadDimVerified = drawing.CadDimVerified,
|
||||
CadDimCount = drawing.CadDimCount,
|
||||
Width = drawing.Width,
|
||||
Length = drawing.Length,
|
||||
RectArea = drawing.RectArea,
|
||||
ExtArea = drawing.ExtArea,
|
||||
TrueArea = drawing.TrueArea,
|
||||
ExtUtil = drawing.ExtUtil,
|
||||
TrueUtil = drawing.TrueUtil,
|
||||
SmallestAreaAng = drawing.SmallestAreaAng,
|
||||
SmallestAreaLen = drawing.SmallestAreaLen,
|
||||
SmallestAreaWid = drawing.SmallestAreaWid,
|
||||
SmallestYAng = drawing.SmallestYAng,
|
||||
SmallestYLen = drawing.SmallestYLen,
|
||||
SmallestYWid = drawing.SmallestYWid,
|
||||
CutLength = drawing.CutLength,
|
||||
ScribeLength = drawing.ScribeLength,
|
||||
Checked = drawing.Checked,
|
||||
PepBendStatus = drawing.PepBendStatus,
|
||||
HasBevel = drawing.HasBevel != 0,
|
||||
HasLeadIn = drawing.HasLeadIn != 0,
|
||||
HasTab = drawing.HasTab != 0,
|
||||
ModifiedDate = drawing.ModifiedDate,
|
||||
ModifiedBy = drawing.ModifiedBy
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Options;
|
||||
using PepApi.Core.Configuration;
|
||||
using PepApi.Core.Models;
|
||||
using PepLib;
|
||||
using PepLib.Data;
|
||||
using PepLib.Models;
|
||||
using Plate = PepApi.Core.Models.Plate;
|
||||
|
||||
namespace PepApi.Core.Controllers;
|
||||
@@ -216,7 +216,12 @@ public class NestsController : ControllerBase
|
||||
nestsQuery = nestsQuery.Where(n => n.DateProgrammed!.Value.Year == year.Value);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(customer))
|
||||
nestsQuery = nestsQuery.Where(n => n.CustomerName == customer || n.CustID == customer);
|
||||
{
|
||||
var customerUpper = customer.Trim().ToUpper();
|
||||
nestsQuery = nestsQuery.Where(n =>
|
||||
(n.CustomerName != null && n.CustomerName.ToUpper().Contains(customerUpper)) ||
|
||||
(n.CustID != null && n.CustID.ToUpper().Contains(customerUpper)));
|
||||
}
|
||||
|
||||
var nests = await nestsQuery
|
||||
.Select(n => new
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using PepApi.Core.Models;
|
||||
using PepLib;
|
||||
using PepLib.Models;
|
||||
|
||||
namespace PepApi.Core
|
||||
{
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
namespace PepApi.Core.Models
|
||||
{
|
||||
public class DrawingDetails
|
||||
{
|
||||
public int ID { get; set; }
|
||||
|
||||
public required string Name { get; set; }
|
||||
|
||||
public required string CustID { get; set; }
|
||||
|
||||
public required string Revision { get; set; }
|
||||
|
||||
public required string Path { get; set; }
|
||||
|
||||
public required string File { get; set; }
|
||||
|
||||
public required string InUseBy { get; set; }
|
||||
|
||||
public DateTime? InUseDate { get; set; }
|
||||
|
||||
public required string Status { get; set; }
|
||||
|
||||
public required string StatusModifiedBy { get; set; }
|
||||
|
||||
public DateTime? StatusModifiedDate { get; set; }
|
||||
|
||||
public DateTime? CreationDate { get; set; }
|
||||
|
||||
public DateTime? LastEditDate { get; set; }
|
||||
|
||||
public DateTime? LastRefDate { get; set; }
|
||||
|
||||
public required string Description { get; set; }
|
||||
|
||||
public required string Customer { get; set; }
|
||||
|
||||
public required string Comment { get; set; }
|
||||
|
||||
public required string Notes { get; set; }
|
||||
|
||||
public byte Grain { get; set; }
|
||||
|
||||
public double GrainAngle { get; set; }
|
||||
|
||||
public required string Material { get; set; }
|
||||
|
||||
public required string MaterialGrade { get; set; }
|
||||
|
||||
public required string Programmer { get; set; }
|
||||
|
||||
public required string CreatedBy { get; set; }
|
||||
|
||||
public required string Type { get; set; }
|
||||
|
||||
public byte CommonCut { get; set; }
|
||||
|
||||
public byte CombineCut { get; set; }
|
||||
|
||||
public required string Errors { get; set; }
|
||||
|
||||
public required string Hardness { get; set; }
|
||||
|
||||
public required string Specification { get; set; }
|
||||
|
||||
public byte NestInCutOuts { get; set; }
|
||||
|
||||
public required string UserDefined1 { get; set; }
|
||||
|
||||
public required string UserDefined2 { get; set; }
|
||||
|
||||
public required string UserDefined3 { get; set; }
|
||||
|
||||
public required string UserDefined4 { get; set; }
|
||||
|
||||
public required string UserDefined5 { get; set; }
|
||||
|
||||
public required string UserDefined6 { get; set; }
|
||||
|
||||
public short Machine { get; set; }
|
||||
|
||||
public required string Application { get; set; }
|
||||
|
||||
public int PartCount { get; set; }
|
||||
|
||||
public int Color { get; set; }
|
||||
|
||||
public short CombineMethod { get; set; }
|
||||
|
||||
public byte SeqCutouts { get; set; }
|
||||
|
||||
public byte AllowMirror { get; set; }
|
||||
|
||||
public required string SourceFile { get; set; }
|
||||
|
||||
public DateTime? SourceDate { get; set; }
|
||||
|
||||
public int SourceSize { get; set; }
|
||||
|
||||
public required string CadScaled { get; set; }
|
||||
|
||||
public int CadDimVerified { get; set; }
|
||||
|
||||
public int CadDimCount { get; set; }
|
||||
|
||||
public double Width { get; set; }
|
||||
|
||||
public double Length { get; set; }
|
||||
|
||||
public double RectArea { get; set; }
|
||||
|
||||
public double ExtArea { get; set; }
|
||||
|
||||
public double TrueArea { get; set; }
|
||||
|
||||
public double ExtUtil { get; set; }
|
||||
|
||||
public double TrueUtil { get; set; }
|
||||
|
||||
public double SmallestAreaAng { get; set; }
|
||||
|
||||
public double SmallestAreaLen { get; set; }
|
||||
|
||||
public double SmallestAreaWid { get; set; }
|
||||
|
||||
public double SmallestYAng { get; set; }
|
||||
|
||||
public double SmallestYLen { get; set; }
|
||||
|
||||
public double SmallestYWid { get; set; }
|
||||
|
||||
public double CutLength { get; set; }
|
||||
|
||||
public double ScribeLength { get; set; }
|
||||
|
||||
public int Checked { get; set; }
|
||||
|
||||
public byte PepBendStatus { get; set; }
|
||||
|
||||
public bool HasBevel { get; set; }
|
||||
|
||||
public bool HasLeadIn { get; set; }
|
||||
|
||||
public bool HasTab { get; set; }
|
||||
|
||||
public DateTime? ModifiedDate { get; set; }
|
||||
|
||||
public required string ModifiedBy { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
namespace PepApi.Core.Models
|
||||
{
|
||||
public class DrawingFilterData
|
||||
{
|
||||
// Text filters (partial, case-insensitive)
|
||||
public string? Name { get; set; }
|
||||
public string? Customer { get; set; }
|
||||
public string? CustID { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? Revision { get; set; }
|
||||
public string? Material { get; set; }
|
||||
public string? MaterialGrade { get; set; }
|
||||
public string? Hardness { get; set; }
|
||||
public string? Specification { get; set; }
|
||||
public string? Programmer { get; set; }
|
||||
public string? CreatedBy { get; set; }
|
||||
public string? ModifiedBy { get; set; }
|
||||
|
||||
// Exact match filters
|
||||
public string? Status { get; set; }
|
||||
public string? Type { get; set; }
|
||||
public string? Application { get; set; }
|
||||
|
||||
// Date range filters
|
||||
public DateTime? CreatedAfter { get; set; }
|
||||
public DateTime? CreatedBefore { get; set; }
|
||||
public DateTime? ModifiedAfter { get; set; }
|
||||
public DateTime? ModifiedBefore { get; set; }
|
||||
public DateTime? LastEditAfter { get; set; }
|
||||
public DateTime? LastEditBefore { get; set; }
|
||||
|
||||
// Dimension range filters
|
||||
public double? MinWidth { get; set; }
|
||||
public double? MaxWidth { get; set; }
|
||||
public double? MinLength { get; set; }
|
||||
public double? MaxLength { get; set; }
|
||||
public double? MinArea { get; set; }
|
||||
public double? MaxArea { get; set; }
|
||||
|
||||
// Boolean filters
|
||||
public bool? HasBevel { get; set; }
|
||||
public bool? HasLeadIn { get; set; }
|
||||
public bool? HasTab { get; set; }
|
||||
|
||||
// Pagination
|
||||
public int Offset { get; set; } = 0;
|
||||
public int Limit { get; set; } = 100;
|
||||
|
||||
public IQueryable<DrawingSummary> Apply(IQueryable<DrawingSummary> drawings)
|
||||
{
|
||||
// Text filters (partial, case-insensitive)
|
||||
if (this.Name != null)
|
||||
{
|
||||
var x = this.Name.ToUpper();
|
||||
drawings = drawings.Where(d => d.Name.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.Customer != null)
|
||||
{
|
||||
var x = this.Customer.ToUpper();
|
||||
drawings = drawings.Where(d => d.Customer.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.CustID != null)
|
||||
{
|
||||
var x = this.CustID.ToUpper();
|
||||
drawings = drawings.Where(d => d.CustID.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.Description != null)
|
||||
{
|
||||
var x = this.Description.ToUpper();
|
||||
drawings = drawings.Where(d => d.Description.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.Revision != null)
|
||||
{
|
||||
var x = this.Revision.ToUpper();
|
||||
drawings = drawings.Where(d => d.Revision.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.Material != null)
|
||||
{
|
||||
var x = this.Material.ToUpper();
|
||||
drawings = drawings.Where(d => d.Material.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.MaterialGrade != null)
|
||||
{
|
||||
var x = this.MaterialGrade.ToUpper();
|
||||
drawings = drawings.Where(d => d.MaterialGrade.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.Programmer != null)
|
||||
{
|
||||
var x = this.Programmer.ToUpper();
|
||||
drawings = drawings.Where(d => d.Programmer.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
if (this.CreatedBy != null)
|
||||
{
|
||||
var x = this.CreatedBy.ToUpper();
|
||||
drawings = drawings.Where(d => d.CreatedBy.ToUpper().Contains(x));
|
||||
}
|
||||
|
||||
// Exact match filters
|
||||
if (this.Status != null)
|
||||
{
|
||||
var x = this.Status.ToUpper();
|
||||
drawings = drawings.Where(d => d.Status.ToUpper() == x);
|
||||
}
|
||||
|
||||
if (this.Type != null)
|
||||
{
|
||||
var x = this.Type.ToUpper();
|
||||
drawings = drawings.Where(d => d.Type.ToUpper() == x);
|
||||
}
|
||||
|
||||
if (this.Application != null)
|
||||
{
|
||||
var x = this.Application.ToUpper();
|
||||
drawings = drawings.Where(d => d.Application.ToUpper() == x);
|
||||
}
|
||||
|
||||
// Date range filters - CreationDate
|
||||
if (this.CreatedAfter != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.CreationDate >= this.CreatedAfter);
|
||||
}
|
||||
|
||||
if (this.CreatedBefore != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.CreationDate <= this.CreatedBefore);
|
||||
}
|
||||
|
||||
// Date range filters - ModifiedDate
|
||||
if (this.ModifiedAfter != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.ModifiedDate >= this.ModifiedAfter);
|
||||
}
|
||||
|
||||
if (this.ModifiedBefore != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.ModifiedDate <= this.ModifiedBefore);
|
||||
}
|
||||
|
||||
// Date range filters - LastEditDate
|
||||
if (this.LastEditAfter != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.LastEditDate >= this.LastEditAfter);
|
||||
}
|
||||
|
||||
if (this.LastEditBefore != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.LastEditDate <= this.LastEditBefore);
|
||||
}
|
||||
|
||||
// Dimension range filters - Width
|
||||
if (this.MinWidth != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.Width >= this.MinWidth);
|
||||
}
|
||||
|
||||
if (this.MaxWidth != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.Width <= this.MaxWidth);
|
||||
}
|
||||
|
||||
// Dimension range filters - Length
|
||||
if (this.MinLength != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.Length >= this.MinLength);
|
||||
}
|
||||
|
||||
if (this.MaxLength != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.Length <= this.MaxLength);
|
||||
}
|
||||
|
||||
// Dimension range filters - Area (TrueArea)
|
||||
if (this.MinArea != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.TrueArea >= this.MinArea);
|
||||
}
|
||||
|
||||
if (this.MaxArea != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.TrueArea <= this.MaxArea);
|
||||
}
|
||||
|
||||
// Boolean filters
|
||||
if (this.HasBevel != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.HasBevel == this.HasBevel);
|
||||
}
|
||||
|
||||
if (this.HasLeadIn != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.HasLeadIn == this.HasLeadIn);
|
||||
}
|
||||
|
||||
if (this.HasTab != null)
|
||||
{
|
||||
drawings = drawings.Where(d => d.HasTab == this.HasTab);
|
||||
}
|
||||
|
||||
return drawings;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace PepApi.Core.Models;
|
||||
|
||||
public class DrawingSearchResponse
|
||||
{
|
||||
public required string SearchTerm { get; set; }
|
||||
public int TotalMatches { get; set; }
|
||||
public int ResultsReturned { get; set; }
|
||||
public List<DrawingSummary> Results { get; set; } = [];
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
namespace PepApi.Core.Models
|
||||
{
|
||||
public class DrawingSummary
|
||||
{
|
||||
public int ID { get; set; }
|
||||
|
||||
public required string Name { get; set; }
|
||||
|
||||
public required string Customer { get; set; }
|
||||
|
||||
public required string CustID { get; set; }
|
||||
|
||||
public required string Revision { get; set; }
|
||||
|
||||
public required string Description { get; set; }
|
||||
|
||||
public required string Material { get; set; }
|
||||
|
||||
public required string MaterialGrade { get; set; }
|
||||
|
||||
public required string Status { get; set; }
|
||||
|
||||
public required string Type { get; set; }
|
||||
|
||||
public required string Application { get; set; }
|
||||
|
||||
public required string Programmer { get; set; }
|
||||
|
||||
public required string CreatedBy { get; set; }
|
||||
|
||||
public double Width { get; set; }
|
||||
|
||||
public double Length { get; set; }
|
||||
|
||||
public double TrueArea { get; set; }
|
||||
|
||||
public double CutLength { get; set; }
|
||||
|
||||
public DateTime? CreationDate { get; set; }
|
||||
|
||||
public DateTime? LastEditDate { get; set; }
|
||||
|
||||
public DateTime? ModifiedDate { get; set; }
|
||||
|
||||
public bool HasBevel { get; set; }
|
||||
|
||||
public bool HasLeadIn { get; set; }
|
||||
|
||||
public bool HasTab { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using PepLib;
|
||||
using PepLib.Models;
|
||||
using Material = PepApi.Core.Models.Material;
|
||||
using Part = PepApi.Core.Models.Part;
|
||||
using Plate = PepApi.Core.Models.Plate;
|
||||
@@ -8,7 +8,7 @@ namespace PepApi.Core
|
||||
{
|
||||
internal static class PepHelper
|
||||
{
|
||||
public static bool IsTestSquare(PepLib.Part part)
|
||||
public static bool IsTestSquare(PepLib.Models.Part part)
|
||||
{
|
||||
if (part == null || part.DrawingName == null)
|
||||
return false;
|
||||
@@ -39,7 +39,7 @@ namespace PepApi.Core
|
||||
return count;
|
||||
}
|
||||
|
||||
public static bool AreTestSquaresInCorrectOrder(PepLib.Plate plate)
|
||||
public static bool AreTestSquaresInCorrectOrder(PepLib.Models.Plate plate)
|
||||
{
|
||||
var partsStarted = false;
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace PepApi.Core
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool AreTestSquaresInCorrectOrder(PepLib.Nest nest)
|
||||
public static bool AreTestSquaresInCorrectOrder(PepLib.Models.Nest nest)
|
||||
{
|
||||
foreach (var plate in nest.Plates)
|
||||
{
|
||||
@@ -229,7 +229,7 @@ namespace PepApi.Core
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public static Material GetMaterial(PepLib.Plate plate)
|
||||
public static Material GetMaterial(PepLib.Models.Plate plate)
|
||||
{
|
||||
return new Material
|
||||
{
|
||||
@@ -240,7 +240,7 @@ namespace PepApi.Core
|
||||
};
|
||||
}
|
||||
|
||||
public static Material GetMaterial(PepLib.Nest nest)
|
||||
public static Material GetMaterial(PepLib.Models.Nest nest)
|
||||
{
|
||||
return GetMaterial(nest.Plates.First());
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
using PepLib.Enums;
|
||||
using PepLib.Geometry;
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public class CircularMove : Motion
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
|
||||
using PepLib.Geometry;
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public class LinearMove : Motion
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
using PepLib.Geometry;
|
||||
using PepLib.Interfaces;
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public abstract class Motion : IMovable, ICode
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace PepLib.Codes
|
||||
using PepLib.Geometry;
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public class RapidMove : Motion
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
|
||||
using PepLib.Enums;
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public class SetKerf : ICode
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
using PepLib.Models;
|
||||
using PepLib.Utilities;
|
||||
|
||||
namespace PepLib.Codes
|
||||
{
|
||||
public class SubProgramCall : ICode
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
namespace PepLib
|
||||
|
||||
namespace PepLib.Enums
|
||||
{
|
||||
public enum ApplicationType
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
namespace PepLib
|
||||
|
||||
namespace PepLib.Enums
|
||||
{
|
||||
public enum DrawingType
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
namespace PepLib
|
||||
|
||||
namespace PepLib.Enums
|
||||
{
|
||||
public enum GrainType
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
namespace PepLib
|
||||
|
||||
namespace PepLib.Enums
|
||||
{
|
||||
public enum KerfType
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Enums
|
||||
{
|
||||
public enum ProgrammingMode
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
namespace PepLib
|
||||
|
||||
namespace PepLib.Enums
|
||||
{
|
||||
public enum RotationType
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
namespace PepLib
|
||||
|
||||
namespace PepLib.Enums
|
||||
{
|
||||
public enum StatusType
|
||||
{
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace PepLib
|
||||
using PepLib.Geometry;
|
||||
using PepLib.Models;
|
||||
|
||||
namespace PepLib.Extensions
|
||||
{
|
||||
public static class PartListExtensions
|
||||
{
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace PepLib
|
||||
using PepLib.Models;
|
||||
|
||||
namespace PepLib.Extensions
|
||||
{
|
||||
public static class PlateListExtensions
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Geometry
|
||||
{
|
||||
public class Box
|
||||
{
|
||||
@@ -10,7 +10,7 @@
|
||||
public Box(double x, double y, double w, double h)
|
||||
{
|
||||
Location = new Vector(x, y);
|
||||
Size = new PepLib.Size(0, 0);
|
||||
Size = new Size(0, 0);
|
||||
Width = w;
|
||||
Height = h;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Geometry
|
||||
{
|
||||
public class Size
|
||||
{
|
||||
@@ -42,4 +42,4 @@
|
||||
return string.Format("{0} x {1}", Height, Width);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
namespace PepLib
|
||||
|
||||
namespace PepLib.Geometry
|
||||
{
|
||||
public class Spacing
|
||||
{
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace PepLib
|
||||
using PepLib.Utilities;
|
||||
|
||||
namespace PepLib.Geometry
|
||||
{
|
||||
public struct Vector
|
||||
{
|
||||
@@ -0,0 +1,6 @@
|
||||
global using PepLib.Enums;
|
||||
global using PepLib.Geometry;
|
||||
global using PepLib.Models;
|
||||
global using PepLib.Utilities;
|
||||
global using PepLib.Extensions;
|
||||
global using PepLib.Interfaces;
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Text;
|
||||
using PepLib.Enums;
|
||||
using PepLib.Models;
|
||||
using PepLib.Utilities;
|
||||
using System.Text;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using PepLib.Models;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Compression;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using PepLib.Codes;
|
||||
using PepLib.Geometry;
|
||||
using PepLib.Models;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Text;
|
||||
using PepLib.Enums;
|
||||
using PepLib.Models;
|
||||
using PepLib.Utilities;
|
||||
using System.Text;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using PepLib.Models;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using PepLib.Codes;
|
||||
using PepLib.Geometry;
|
||||
using PepLib.Models;
|
||||
using PepLib.Utilities;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using PepLib.Codes;
|
||||
using PepLib.Enums;
|
||||
using PepLib.Geometry;
|
||||
using PepLib.Models;
|
||||
using System.Text;
|
||||
|
||||
namespace PepLib.IO
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using PepLib.Models;
|
||||
using PepLib.Utilities;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace PepLib.IO
|
||||
{
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace PepLib
|
||||
using PepLib.Geometry;
|
||||
|
||||
namespace PepLib.Interfaces
|
||||
{
|
||||
public interface IMovable
|
||||
{
|
||||
@@ -1,7 +1,8 @@
|
||||
using PepLib.Codes;
|
||||
using PepLib.Codes;
|
||||
using PepLib.Enums;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepLib
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public class Drawing
|
||||
{
|
||||
@@ -1,6 +1,7 @@
|
||||
using PepLib.Enums;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepLib
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public class DrawingInfo
|
||||
{
|
||||
@@ -103,4 +104,3 @@ namespace PepLib
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using PepLib.Codes;
|
||||
using PepLib.Codes;
|
||||
using PepLib.Enums;
|
||||
using PepLib.Geometry;
|
||||
|
||||
namespace PepLib
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public class Loop : Program
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public class Machine
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public class Material
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using PepLib.Codes;
|
||||
using PepLib.Codes;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepLib
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public class Nest
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public class NestDrawing
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using PepLib.IO;
|
||||
using PepLib.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace PepLib
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public class NestIndex
|
||||
{
|
||||
@@ -1,6 +1,7 @@
|
||||
using PepLib.IO;
|
||||
using PepLib.Enums;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepLib
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public class NestInfo
|
||||
{
|
||||
@@ -94,4 +95,4 @@ namespace PepLib
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
namespace PepLib
|
||||
using PepLib.Enums;
|
||||
using PepLib.Geometry;
|
||||
using PepLib.Interfaces;
|
||||
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public class Part : IMovable
|
||||
{
|
||||
@@ -1,4 +1,9 @@
|
||||
namespace PepLib
|
||||
using PepLib.Extensions;
|
||||
using PepLib.Geometry;
|
||||
using PepLib.Interfaces;
|
||||
using PepLib.Utilities;
|
||||
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public class Plate : IMovable
|
||||
{
|
||||
@@ -0,0 +1,226 @@
|
||||
using PepLib.Codes;
|
||||
using PepLib.Enums;
|
||||
using PepLib.Geometry;
|
||||
using PepLib.Interfaces;
|
||||
using PepLib.IO;
|
||||
using PepLib.Utilities;
|
||||
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public class Program : List<ICode>, IMovable
|
||||
{
|
||||
private ProgrammingMode mode;
|
||||
|
||||
public Program(ProgrammingMode mode = ProgrammingMode.Absolute)
|
||||
{
|
||||
Mode = mode;
|
||||
}
|
||||
|
||||
public ProgrammingMode Mode
|
||||
{
|
||||
get => mode;
|
||||
set
|
||||
{
|
||||
if (value == ProgrammingMode.Absolute)
|
||||
SetProgrammingModeAbs();
|
||||
else
|
||||
SetProgrammingModeInc();
|
||||
}
|
||||
}
|
||||
|
||||
public double Rotation { get; protected set; }
|
||||
|
||||
private void SetProgrammingModeInc()
|
||||
{
|
||||
if (mode == ProgrammingMode.Incremental)
|
||||
return;
|
||||
|
||||
var pos = new Vector(0, 0);
|
||||
|
||||
foreach (var code in this)
|
||||
{
|
||||
if (code is Motion motion)
|
||||
{
|
||||
var pos2 = motion.EndPoint;
|
||||
motion.Offset(-pos.X, -pos.Y);
|
||||
pos = pos2;
|
||||
}
|
||||
}
|
||||
|
||||
mode = ProgrammingMode.Incremental;
|
||||
}
|
||||
|
||||
private void SetProgrammingModeAbs()
|
||||
{
|
||||
if (mode == ProgrammingMode.Absolute)
|
||||
return;
|
||||
|
||||
var pos = new Vector(0, 0);
|
||||
|
||||
foreach (var code in this)
|
||||
{
|
||||
if (code is Motion motion)
|
||||
{
|
||||
motion.Offset(pos);
|
||||
pos = motion.EndPoint;
|
||||
}
|
||||
}
|
||||
|
||||
mode = ProgrammingMode.Absolute;
|
||||
}
|
||||
|
||||
public virtual void Rotate(double angle) =>
|
||||
ApplyTransform(code => (code as IMovable)?.Rotate(angle), angle);
|
||||
|
||||
public virtual void Rotate(double angle, Vector origin) =>
|
||||
ApplyTransform(code => (code as IMovable)?.Rotate(angle, origin), angle);
|
||||
|
||||
public void Offset(double x, double y) =>
|
||||
ApplyTransform(code => (code as IMovable)?.Offset(x, y));
|
||||
|
||||
public void Offset(Vector voffset) =>
|
||||
ApplyTransform(code => (code as IMovable)?.Offset(voffset));
|
||||
|
||||
private void ApplyTransform(Action<ICode> transform, double? rotationAngle = null)
|
||||
{
|
||||
var previousMode = Mode;
|
||||
SetProgrammingModeAbs();
|
||||
|
||||
foreach (var code in this)
|
||||
{
|
||||
if (rotationAngle.HasValue && code is SubProgramCall subpgm)
|
||||
{
|
||||
subpgm.Loop?.Rotate(rotationAngle.Value);
|
||||
}
|
||||
|
||||
transform(code);
|
||||
}
|
||||
|
||||
if (previousMode == ProgrammingMode.Incremental)
|
||||
SetProgrammingModeInc();
|
||||
|
||||
if (rotationAngle.HasValue)
|
||||
Rotation = MathHelper.NormalizeAngleRad(Rotation + rotationAngle.Value);
|
||||
}
|
||||
|
||||
public Box GetBoundingBox()
|
||||
{
|
||||
var origin = new Vector(0, 0);
|
||||
return GetBoundingBox(ref origin);
|
||||
}
|
||||
|
||||
private Box GetBoundingBox(ref Vector pos)
|
||||
{
|
||||
var bounds = new BoundsTracker();
|
||||
|
||||
foreach (var code in this)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case LinearMove line:
|
||||
pos = ProcessLinearMotion(line.EndPoint, pos, bounds);
|
||||
break;
|
||||
|
||||
case RapidMove rapid:
|
||||
pos = ProcessLinearMotion(rapid.EndPoint, pos, bounds);
|
||||
break;
|
||||
|
||||
case CircularMove arc:
|
||||
pos = ProcessCircularMotion(arc, pos, bounds);
|
||||
break;
|
||||
|
||||
case SubProgramCall subpgm:
|
||||
var box = subpgm.Loop.GetBoundingBox(ref pos);
|
||||
bounds.ExpandTo(box);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return bounds.ToBox();
|
||||
}
|
||||
|
||||
private Vector ProcessLinearMotion(Vector endPoint, Vector pos, BoundsTracker bounds)
|
||||
{
|
||||
var pt = Mode == ProgrammingMode.Absolute ? endPoint : endPoint + pos;
|
||||
bounds.Include(pt);
|
||||
return pt;
|
||||
}
|
||||
|
||||
private Vector ProcessCircularMotion(CircularMove arc, Vector pos, BoundsTracker bounds)
|
||||
{
|
||||
var radius = arc.CenterPoint.DistanceTo(arc.EndPoint);
|
||||
|
||||
var (endpt, centerpt) = Mode == ProgrammingMode.Incremental
|
||||
? (arc.EndPoint + pos, arc.CenterPoint + pos)
|
||||
: (arc.EndPoint, arc.CenterPoint);
|
||||
|
||||
// Start with endpoint bounds
|
||||
var minX = Math.Min(pos.X, endpt.X);
|
||||
var maxX = Math.Max(pos.X, endpt.X);
|
||||
var minY = Math.Min(pos.Y, endpt.Y);
|
||||
var maxY = Math.Max(pos.Y, endpt.Y);
|
||||
|
||||
// Check if arc crosses cardinal directions
|
||||
var startAngle = MathHelper.NormalizeAngleRad(pos.AngleFrom(centerpt));
|
||||
var endAngle = MathHelper.NormalizeAngleRad(endpt.AngleFrom(centerpt));
|
||||
|
||||
// Switch angles for clockwise arcs
|
||||
if (arc.Rotation == RotationType.CW)
|
||||
Generic.Swap(ref startAngle, ref endAngle);
|
||||
|
||||
// Expand bounds if arc crosses cardinal points
|
||||
if (MathHelper.IsAngleBetween(MathHelper.HalfPI, startAngle, endAngle))
|
||||
maxY = centerpt.Y + radius;
|
||||
|
||||
if (MathHelper.IsAngleBetween(Math.PI, startAngle, endAngle))
|
||||
minX = centerpt.X - radius;
|
||||
|
||||
if (MathHelper.IsAngleBetween(Math.PI * 1.5, startAngle, endAngle))
|
||||
minY = centerpt.Y - radius;
|
||||
|
||||
if (MathHelper.IsAngleBetween(MathHelper.TwoPI, startAngle, endAngle))
|
||||
maxX = centerpt.X + radius;
|
||||
|
||||
bounds.Expand(minX, minY, maxX, maxY);
|
||||
return endpt;
|
||||
}
|
||||
|
||||
public static Program Load(Stream stream)
|
||||
{
|
||||
var reader = new ProgramReader();
|
||||
reader.Read(stream);
|
||||
return reader.Program;
|
||||
}
|
||||
|
||||
private class BoundsTracker
|
||||
{
|
||||
private double minX, minY, maxX, maxY;
|
||||
|
||||
public void Include(Vector pt)
|
||||
{
|
||||
if (pt.X < minX) minX = pt.X;
|
||||
if (pt.X > maxX) maxX = pt.X;
|
||||
if (pt.Y < minY) minY = pt.Y;
|
||||
if (pt.Y > maxY) maxY = pt.Y;
|
||||
}
|
||||
|
||||
public void Expand(double left, double bottom, double right, double top)
|
||||
{
|
||||
if (left < minX) minX = left;
|
||||
if (right > maxX) maxX = right;
|
||||
if (bottom < minY) minY = bottom;
|
||||
if (top > maxY) maxY = top;
|
||||
}
|
||||
|
||||
public void ExpandTo(Box box)
|
||||
{
|
||||
if (box.Left < minX) minX = box.Left;
|
||||
if (box.Right > maxX) maxX = box.Right;
|
||||
if (box.Bottom < minY) minY = box.Bottom;
|
||||
if (box.Top > maxY) maxY = box.Top;
|
||||
}
|
||||
|
||||
public Box ToBox() => new(minX, minY, maxX - minX, maxY - minY);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public partial class Report
|
||||
{
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
namespace PepLib
|
||||
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public partial class Report
|
||||
{
|
||||
@@ -1,6 +1,6 @@
|
||||
using PepLib.IO;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepLib
|
||||
namespace PepLib.Models
|
||||
{
|
||||
public partial class Report
|
||||
{
|
||||
@@ -118,4 +118,4 @@ namespace PepLib
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,364 +0,0 @@
|
||||
using PepLib.Codes;
|
||||
using PepLib.IO;
|
||||
|
||||
namespace PepLib
|
||||
{
|
||||
public class Program : List<ICode>, IMovable
|
||||
{
|
||||
private ProgrammingMode mode;
|
||||
|
||||
public Program(ProgrammingMode mode = ProgrammingMode.Absolute)
|
||||
{
|
||||
Mode = mode;
|
||||
}
|
||||
|
||||
public ProgrammingMode Mode
|
||||
{
|
||||
get { return mode; }
|
||||
set
|
||||
{
|
||||
if (value == ProgrammingMode.Absolute)
|
||||
SetProgrammingModeAbs();
|
||||
else
|
||||
SetProgrammingModeInc();
|
||||
}
|
||||
}
|
||||
|
||||
public double Rotation { get; protected set; }
|
||||
|
||||
private void SetProgrammingModeInc()
|
||||
{
|
||||
if (mode == ProgrammingMode.Incremental)
|
||||
return;
|
||||
|
||||
var pos = new Vector(0, 0);
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
var motion = code as Motion;
|
||||
|
||||
if (motion != null)
|
||||
{
|
||||
var pos2 = motion.EndPoint;
|
||||
motion.Offset(-pos.X, -pos.Y);
|
||||
pos = pos2;
|
||||
}
|
||||
}
|
||||
|
||||
mode = ProgrammingMode.Incremental;
|
||||
}
|
||||
|
||||
private void SetProgrammingModeAbs()
|
||||
{
|
||||
if (mode == ProgrammingMode.Absolute)
|
||||
return;
|
||||
|
||||
var pos = new Vector(0, 0);
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
var motion = code as Motion;
|
||||
|
||||
if (motion != null)
|
||||
{
|
||||
motion.Offset(pos);
|
||||
pos = motion.EndPoint;
|
||||
}
|
||||
}
|
||||
|
||||
mode = ProgrammingMode.Absolute;
|
||||
}
|
||||
|
||||
public virtual void Rotate(double angle)
|
||||
{
|
||||
var mode = Mode;
|
||||
|
||||
SetProgrammingModeAbs();
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
|
||||
if (code.CodeType() == CodeType.SubProgramCall)
|
||||
{
|
||||
var subpgm = (SubProgramCall)code;
|
||||
|
||||
if (subpgm.Loop != null)
|
||||
subpgm.Loop.Rotate(angle);
|
||||
}
|
||||
|
||||
if (code is IMovable == false)
|
||||
continue;
|
||||
|
||||
var code2 = (IMovable)code;
|
||||
|
||||
code2.Rotate(angle);
|
||||
}
|
||||
|
||||
if (mode == ProgrammingMode.Incremental)
|
||||
SetProgrammingModeInc();
|
||||
|
||||
Rotation = MathHelper.NormalizeAngleRad(Rotation + angle);
|
||||
}
|
||||
|
||||
public virtual void Rotate(double angle, Vector origin)
|
||||
{
|
||||
var mode = Mode;
|
||||
|
||||
SetProgrammingModeAbs();
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
|
||||
if (code.CodeType() == CodeType.SubProgramCall)
|
||||
{
|
||||
var subpgm = (SubProgramCall)code;
|
||||
|
||||
if (subpgm.Loop != null)
|
||||
subpgm.Loop.Rotate(angle);
|
||||
}
|
||||
|
||||
if (code is IMovable == false)
|
||||
continue;
|
||||
|
||||
var code2 = (IMovable)code;
|
||||
|
||||
code2.Rotate(angle, origin);
|
||||
}
|
||||
|
||||
if (mode == ProgrammingMode.Incremental)
|
||||
SetProgrammingModeInc();
|
||||
|
||||
Rotation = MathHelper.NormalizeAngleRad(Rotation + angle);
|
||||
}
|
||||
|
||||
public void Offset(double x, double y)
|
||||
{
|
||||
var mode = Mode;
|
||||
|
||||
SetProgrammingModeAbs();
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
|
||||
if (code is IMovable == false)
|
||||
continue;
|
||||
|
||||
var code2 = (IMovable)code;
|
||||
|
||||
code2.Offset(x, y);
|
||||
}
|
||||
|
||||
if (mode == ProgrammingMode.Incremental)
|
||||
SetProgrammingModeInc();
|
||||
}
|
||||
|
||||
public void Offset(Vector voffset)
|
||||
{
|
||||
var mode = Mode;
|
||||
|
||||
SetProgrammingModeAbs();
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
|
||||
if (code is IMovable == false)
|
||||
continue;
|
||||
|
||||
var code2 = (IMovable)code;
|
||||
|
||||
code2.Offset(voffset);
|
||||
}
|
||||
|
||||
if (mode == ProgrammingMode.Incremental)
|
||||
SetProgrammingModeInc();
|
||||
}
|
||||
|
||||
public Box GetBoundingBox()
|
||||
{
|
||||
var origin = new Vector(0, 0);
|
||||
return GetBoundingBox(ref origin);
|
||||
}
|
||||
|
||||
private Box GetBoundingBox(ref Vector pos)
|
||||
{
|
||||
double minX = 0.0;
|
||||
double minY = 0.0;
|
||||
double maxX = 0.0;
|
||||
double maxY = 0.0;
|
||||
|
||||
for (int i = 0; i < Count; ++i)
|
||||
{
|
||||
var code = this[i];
|
||||
|
||||
switch (code.CodeType())
|
||||
{
|
||||
case CodeType.LinearMove:
|
||||
{
|
||||
var line = (LinearMove)code;
|
||||
var pt = Mode == ProgrammingMode.Absolute ?
|
||||
line.EndPoint :
|
||||
line.EndPoint + pos;
|
||||
|
||||
if (pt.X > maxX)
|
||||
maxX = pt.X;
|
||||
else if (pt.X < minX)
|
||||
minX = pt.X;
|
||||
|
||||
if (pt.Y > maxY)
|
||||
maxY = pt.Y;
|
||||
else if (pt.Y < minY)
|
||||
minY = pt.Y;
|
||||
|
||||
pos = pt;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CodeType.RapidMove:
|
||||
{
|
||||
var line = (RapidMove)code;
|
||||
var pt = Mode == ProgrammingMode.Absolute
|
||||
? line.EndPoint
|
||||
: line.EndPoint + pos;
|
||||
|
||||
if (pt.X > maxX)
|
||||
maxX = pt.X;
|
||||
else if (pt.X < minX)
|
||||
minX = pt.X;
|
||||
|
||||
if (pt.Y > maxY)
|
||||
maxY = pt.Y;
|
||||
else if (pt.Y < minY)
|
||||
minY = pt.Y;
|
||||
|
||||
pos = pt;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CodeType.CircularMove:
|
||||
{
|
||||
var arc = (CircularMove)code;
|
||||
var radius = arc.CenterPoint.DistanceTo(arc.EndPoint);
|
||||
|
||||
Vector endpt;
|
||||
Vector centerpt;
|
||||
|
||||
if (Mode == ProgrammingMode.Incremental)
|
||||
{
|
||||
endpt = arc.EndPoint + pos;
|
||||
centerpt = arc.CenterPoint + pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
endpt = arc.EndPoint;
|
||||
centerpt = arc.CenterPoint;
|
||||
}
|
||||
|
||||
double minX1;
|
||||
double minY1;
|
||||
double maxX1;
|
||||
double maxY1;
|
||||
|
||||
if (pos.X < endpt.X)
|
||||
{
|
||||
minX1 = pos.X;
|
||||
maxX1 = endpt.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
minX1 = endpt.X;
|
||||
maxX1 = pos.X;
|
||||
}
|
||||
|
||||
if (pos.Y < endpt.Y)
|
||||
{
|
||||
minY1 = pos.Y;
|
||||
maxY1 = endpt.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
minY1 = endpt.Y;
|
||||
maxY1 = pos.Y;
|
||||
}
|
||||
|
||||
var startAngle = pos.AngleFrom(centerpt);
|
||||
var endAngle = endpt.AngleFrom(centerpt);
|
||||
|
||||
// switch the angle to counter clockwise.
|
||||
if (arc.Rotation == RotationType.CW)
|
||||
Generic.Swap(ref startAngle, ref endAngle);
|
||||
|
||||
startAngle = MathHelper.NormalizeAngleRad(startAngle);
|
||||
endAngle = MathHelper.NormalizeAngleRad(endAngle);
|
||||
|
||||
if (MathHelper.IsAngleBetween(MathHelper.HalfPI, startAngle, endAngle))
|
||||
maxY1 = centerpt.Y + radius;
|
||||
|
||||
if (MathHelper.IsAngleBetween(Math.PI, startAngle, endAngle))
|
||||
minX1 = centerpt.X - radius;
|
||||
|
||||
const double oneHalfPI = Math.PI * 1.5;
|
||||
|
||||
if (MathHelper.IsAngleBetween(oneHalfPI, startAngle, endAngle))
|
||||
minY1 = centerpt.Y - radius;
|
||||
|
||||
if (MathHelper.IsAngleBetween(MathHelper.TwoPI, startAngle, endAngle))
|
||||
maxX1 = centerpt.X + radius;
|
||||
|
||||
if (maxX1 > maxX)
|
||||
maxX = maxX1;
|
||||
|
||||
if (minX1 < minX)
|
||||
minX = minX1;
|
||||
|
||||
if (maxY1 > maxY)
|
||||
maxY = maxY1;
|
||||
|
||||
if (minY1 < minY)
|
||||
minY = minY1;
|
||||
|
||||
pos = endpt;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case CodeType.SubProgramCall:
|
||||
{
|
||||
var subpgm = (SubProgramCall)code;
|
||||
var box = subpgm.Loop.GetBoundingBox(ref pos);
|
||||
|
||||
if (box.Left < minX)
|
||||
minX = box.Left;
|
||||
|
||||
if (box.Right > maxX)
|
||||
maxX = box.Right;
|
||||
|
||||
if (box.Bottom < minY)
|
||||
minY = box.Bottom;
|
||||
|
||||
if (box.Top > maxY)
|
||||
maxY = box.Top;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Box(minX, minY, maxX - minX, maxY - minY);
|
||||
}
|
||||
|
||||
public static Program Load(Stream stream)
|
||||
{
|
||||
var reader = new ProgramReader();
|
||||
reader.Read(stream);
|
||||
return reader.Program;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Utilities
|
||||
{
|
||||
public static class AngleConverter
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Utilities
|
||||
{
|
||||
public static class Generic
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Utilities
|
||||
{
|
||||
public class IniConfig
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Utilities
|
||||
{
|
||||
public static class MathHelper
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Utilities
|
||||
{
|
||||
public class Node
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace PepLib
|
||||
namespace PepLib.Utilities
|
||||
{
|
||||
public static class Tolerance
|
||||
{
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace PepLib
|
||||
namespace PepLib.Utilities
|
||||
{
|
||||
public static class Util
|
||||
{
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.IO.Compression;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace PepLib
|
||||
namespace PepLib.Utilities
|
||||
{
|
||||
public static class ZipHelper
|
||||
{
|
||||
@@ -79,4 +79,3 @@ namespace PepLib
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,4 +400,175 @@ public class PepTools
|
||||
return $"Error calling PEP API: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
[McpServerTool, Description("Get a list of drawings with comprehensive filtering options for all fields including dimensions, dates, and boolean flags.")]
|
||||
public static async Task<string> GetDrawings(
|
||||
[Description("Filter by partial name (case-insensitive)")] string? name = null,
|
||||
[Description("Filter by partial customer name (case-insensitive)")] string? customer = null,
|
||||
[Description("Filter by partial customer ID (case-insensitive)")] string? custId = null,
|
||||
[Description("Filter by partial description (case-insensitive)")] string? description = null,
|
||||
[Description("Filter by partial revision (case-insensitive)")] string? revision = null,
|
||||
[Description("Filter by partial material (case-insensitive)")] string? material = null,
|
||||
[Description("Filter by partial material grade (case-insensitive)")] string? materialGrade = null,
|
||||
[Description("Filter by partial programmer name (case-insensitive)")] string? programmer = null,
|
||||
[Description("Filter by partial created by (case-insensitive)")] string? createdBy = null,
|
||||
[Description("Filter by exact status match")] string? status = null,
|
||||
[Description("Filter by exact type match")] string? type = null,
|
||||
[Description("Filter by exact application match")] string? application = null,
|
||||
[Description("Filter by creation date after (yyyy-MM-dd)")] string? createdAfter = null,
|
||||
[Description("Filter by creation date before (yyyy-MM-dd)")] string? createdBefore = null,
|
||||
[Description("Filter by modified date after (yyyy-MM-dd)")] string? modifiedAfter = null,
|
||||
[Description("Filter by modified date before (yyyy-MM-dd)")] string? modifiedBefore = null,
|
||||
[Description("Filter by minimum width")] double? minWidth = null,
|
||||
[Description("Filter by maximum width")] double? maxWidth = null,
|
||||
[Description("Filter by minimum length")] double? minLength = null,
|
||||
[Description("Filter by maximum length")] double? maxLength = null,
|
||||
[Description("Filter by minimum area")] double? minArea = null,
|
||||
[Description("Filter by maximum area")] double? maxArea = null,
|
||||
[Description("Filter by has bevel")] bool? hasBevel = null,
|
||||
[Description("Filter by has lead-in")] bool? hasLeadIn = null,
|
||||
[Description("Filter by has tab")] bool? hasTab = null,
|
||||
[Description("Number of results to skip (default 0)")] int offset = 0,
|
||||
[Description("Maximum number of results to return (default 100)")] int limit = 100)
|
||||
{
|
||||
try
|
||||
{
|
||||
var queryParams = new List<string>();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(name))
|
||||
queryParams.Add($"name={Uri.EscapeDataString(name)}");
|
||||
if (!string.IsNullOrWhiteSpace(customer))
|
||||
queryParams.Add($"customer={Uri.EscapeDataString(customer)}");
|
||||
if (!string.IsNullOrWhiteSpace(custId))
|
||||
queryParams.Add($"custId={Uri.EscapeDataString(custId)}");
|
||||
if (!string.IsNullOrWhiteSpace(description))
|
||||
queryParams.Add($"description={Uri.EscapeDataString(description)}");
|
||||
if (!string.IsNullOrWhiteSpace(revision))
|
||||
queryParams.Add($"revision={Uri.EscapeDataString(revision)}");
|
||||
if (!string.IsNullOrWhiteSpace(material))
|
||||
queryParams.Add($"material={Uri.EscapeDataString(material)}");
|
||||
if (!string.IsNullOrWhiteSpace(materialGrade))
|
||||
queryParams.Add($"materialGrade={Uri.EscapeDataString(materialGrade)}");
|
||||
if (!string.IsNullOrWhiteSpace(programmer))
|
||||
queryParams.Add($"programmer={Uri.EscapeDataString(programmer)}");
|
||||
if (!string.IsNullOrWhiteSpace(createdBy))
|
||||
queryParams.Add($"createdBy={Uri.EscapeDataString(createdBy)}");
|
||||
if (!string.IsNullOrWhiteSpace(status))
|
||||
queryParams.Add($"status={Uri.EscapeDataString(status)}");
|
||||
if (!string.IsNullOrWhiteSpace(type))
|
||||
queryParams.Add($"type={Uri.EscapeDataString(type)}");
|
||||
if (!string.IsNullOrWhiteSpace(application))
|
||||
queryParams.Add($"application={Uri.EscapeDataString(application)}");
|
||||
if (!string.IsNullOrWhiteSpace(createdAfter))
|
||||
queryParams.Add($"createdAfter={Uri.EscapeDataString(createdAfter)}");
|
||||
if (!string.IsNullOrWhiteSpace(createdBefore))
|
||||
queryParams.Add($"createdBefore={Uri.EscapeDataString(createdBefore)}");
|
||||
if (!string.IsNullOrWhiteSpace(modifiedAfter))
|
||||
queryParams.Add($"modifiedAfter={Uri.EscapeDataString(modifiedAfter)}");
|
||||
if (!string.IsNullOrWhiteSpace(modifiedBefore))
|
||||
queryParams.Add($"modifiedBefore={Uri.EscapeDataString(modifiedBefore)}");
|
||||
if (minWidth.HasValue)
|
||||
queryParams.Add($"minWidth={minWidth.Value}");
|
||||
if (maxWidth.HasValue)
|
||||
queryParams.Add($"maxWidth={maxWidth.Value}");
|
||||
if (minLength.HasValue)
|
||||
queryParams.Add($"minLength={minLength.Value}");
|
||||
if (maxLength.HasValue)
|
||||
queryParams.Add($"maxLength={maxLength.Value}");
|
||||
if (minArea.HasValue)
|
||||
queryParams.Add($"minArea={minArea.Value}");
|
||||
if (maxArea.HasValue)
|
||||
queryParams.Add($"maxArea={maxArea.Value}");
|
||||
if (hasBevel.HasValue)
|
||||
queryParams.Add($"hasBevel={hasBevel.Value.ToString().ToLower()}");
|
||||
if (hasLeadIn.HasValue)
|
||||
queryParams.Add($"hasLeadIn={hasLeadIn.Value.ToString().ToLower()}");
|
||||
if (hasTab.HasValue)
|
||||
queryParams.Add($"hasTab={hasTab.Value.ToString().ToLower()}");
|
||||
|
||||
queryParams.Add($"offset={offset}");
|
||||
queryParams.Add($"limit={limit}");
|
||||
|
||||
var query = "?" + string.Join("&", queryParams);
|
||||
var response = await _httpClient.GetAsync($"/drawings{query}");
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return $"Error: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}";
|
||||
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
return json;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return $"Error calling PEP API: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
[McpServerTool, Description("Get detailed information about a specific drawing by its ID.")]
|
||||
public static async Task<string> GetDrawing(
|
||||
[Description("The drawing ID to look up")] int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.GetAsync($"/drawings/{id}");
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return $"Error: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}";
|
||||
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
return json;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return $"Error calling PEP API: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
[McpServerTool, Description("Get detailed information about a specific drawing by its exact name.")]
|
||||
public static async Task<string> GetDrawingByName(
|
||||
[Description("The exact drawing name to look up")] string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await _httpClient.GetAsync($"/drawings/name/{Uri.EscapeDataString(name)}");
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return $"Error: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}";
|
||||
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
return json;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return $"Error calling PEP API: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
[McpServerTool, Description("Search for drawings by partial name match. Returns matching drawings with basic information.")]
|
||||
public static async Task<string> SearchDrawings(
|
||||
[Description("The partial drawing name to search for")] string searchTerm,
|
||||
[Description("Maximum number of results to return (default 100)")] int limit = 100)
|
||||
{
|
||||
try
|
||||
{
|
||||
var queryParams = new List<string>
|
||||
{
|
||||
$"search={Uri.EscapeDataString(searchTerm)}",
|
||||
$"limit={limit}"
|
||||
};
|
||||
|
||||
var query = "?" + string.Join("&", queryParams);
|
||||
var response = await _httpClient.GetAsync($"/drawings/search{query}");
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
return $"Error: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}";
|
||||
|
||||
var json = await response.Content.ReadAsStringAsync();
|
||||
return json;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return $"Error calling PEP API: {ex.Message}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,314 @@
|
||||
# Claude Code MCP Server Management
|
||||
|
||||
> Source: https://code.claude.com/docs/en/mcp (fetched 2026-02-06)
|
||||
|
||||
## Quick Reference - Managing Servers
|
||||
|
||||
### CLI Commands
|
||||
|
||||
```bash
|
||||
# List all configured servers
|
||||
claude mcp list
|
||||
|
||||
# Get details for a specific server
|
||||
claude mcp get <name>
|
||||
|
||||
# Remove a server
|
||||
claude mcp remove <name>
|
||||
|
||||
# Add servers
|
||||
claude mcp add --transport http <name> <url>
|
||||
claude mcp add --transport sse <name> <url>
|
||||
claude mcp add --transport stdio <name> -- <command> [args...]
|
||||
claude mcp add-json <name> '<json>'
|
||||
|
||||
# Import from Claude Desktop
|
||||
claude mcp add-from-claude-desktop
|
||||
|
||||
# Reset project approval choices
|
||||
claude mcp reset-project-choices
|
||||
```
|
||||
|
||||
### In-Session Management
|
||||
|
||||
- **`/mcp`** - View and manage all MCP servers, check status, authenticate, reconnect
|
||||
- **`@` mentions** - Toggle MCP servers on/off during a session (enable/disable)
|
||||
|
||||
### Restarting After Changes
|
||||
|
||||
After editing config files directly, restart Claude Code for changes to take effect.
|
||||
|
||||
---
|
||||
|
||||
## Installing MCP Servers
|
||||
|
||||
### Option 1: Remote HTTP Server (Recommended)
|
||||
|
||||
```bash
|
||||
claude mcp add --transport http <name> <url>
|
||||
|
||||
# With Bearer token
|
||||
claude mcp add --transport http secure-api https://api.example.com/mcp \
|
||||
--header "Authorization: Bearer your-token"
|
||||
```
|
||||
|
||||
### Option 2: Remote SSE Server (Deprecated)
|
||||
|
||||
```bash
|
||||
claude mcp add --transport sse <name> <url>
|
||||
|
||||
# With auth header
|
||||
claude mcp add --transport sse private-api https://api.company.com/sse \
|
||||
--header "X-API-Key: your-key-here"
|
||||
```
|
||||
|
||||
### Option 3: Local stdio Server
|
||||
|
||||
```bash
|
||||
claude mcp add [options] <name> -- <command> [args...]
|
||||
|
||||
# Example
|
||||
claude mcp add --transport stdio --env AIRTABLE_API_KEY=YOUR_KEY airtable \
|
||||
-- npx -y airtable-mcp-server
|
||||
```
|
||||
|
||||
**Important: Option ordering** - All options (`--transport`, `--env`, `--scope`, `--header`) must come **before** the server name. The `--` separates the server name from the command/args.
|
||||
|
||||
### Add from JSON
|
||||
|
||||
```bash
|
||||
claude mcp add-json <name> '<json>'
|
||||
|
||||
# HTTP example
|
||||
claude mcp add-json weather-api '{"type":"http","url":"https://api.weather.com/mcp","headers":{"Authorization":"Bearer token"}}'
|
||||
|
||||
# stdio example
|
||||
claude mcp add-json local-tool '{"type":"stdio","command":"/path/to/server","args":["--flag"],"env":{"KEY":"value"}}'
|
||||
```
|
||||
|
||||
### Windows Note
|
||||
|
||||
On native Windows (not WSL), local MCP servers using `npx` require the `cmd /c` wrapper:
|
||||
|
||||
```bash
|
||||
claude mcp add --transport stdio my-server -- cmd /c npx -y @some/package
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MCP Installation Scopes
|
||||
|
||||
### Local Scope (Default)
|
||||
|
||||
Private to you, only accessible in current project. Stored in `~/.claude.json` under project path.
|
||||
|
||||
```bash
|
||||
claude mcp add --transport http stripe --scope local https://mcp.stripe.com
|
||||
```
|
||||
|
||||
### Project Scope
|
||||
|
||||
Shared via `.mcp.json` at project root (checked into version control).
|
||||
|
||||
```bash
|
||||
claude mcp add --transport http paypal --scope project https://mcp.paypal.com/mcp
|
||||
```
|
||||
|
||||
`.mcp.json` format:
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"shared-server": {
|
||||
"command": "/path/to/server",
|
||||
"args": [],
|
||||
"env": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### User Scope
|
||||
|
||||
Available across all projects, private to your account. Stored in `~/.claude.json`.
|
||||
|
||||
```bash
|
||||
claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic
|
||||
```
|
||||
|
||||
### Precedence
|
||||
|
||||
Local > Project > User (local overrides project, project overrides user).
|
||||
|
||||
---
|
||||
|
||||
## Environment Variable Expansion in .mcp.json
|
||||
|
||||
Supported syntax:
|
||||
- `${VAR}` - Expands to value of VAR
|
||||
- `${VAR:-default}` - Uses default if VAR not set
|
||||
|
||||
Works in: `command`, `args`, `env`, `url`, `headers`
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"api-server": {
|
||||
"type": "http",
|
||||
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
|
||||
"headers": {
|
||||
"Authorization": "Bearer ${API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## OAuth Authentication
|
||||
|
||||
```bash
|
||||
# Add server requiring auth
|
||||
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
|
||||
|
||||
# Then authenticate in Claude Code
|
||||
> /mcp
|
||||
# Follow browser login flow
|
||||
```
|
||||
|
||||
### Pre-configured OAuth Credentials
|
||||
|
||||
For servers that don't support dynamic client registration:
|
||||
|
||||
```bash
|
||||
claude mcp add --transport http \
|
||||
--client-id your-client-id --client-secret --callback-port 8080 \
|
||||
my-server https://mcp.example.com/mcp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MCP Tool Search
|
||||
|
||||
Automatically enabled when MCP tool descriptions exceed 10% of context window. Tools are loaded on-demand instead of all upfront.
|
||||
|
||||
Configure with `ENABLE_TOOL_SEARCH` environment variable:
|
||||
|
||||
| Value | Behavior |
|
||||
|-------|----------|
|
||||
| `auto` | Activates at 10% threshold (default) |
|
||||
| `auto:<N>` | Custom threshold percentage |
|
||||
| `true` | Always enabled |
|
||||
| `false` | Disabled, all tools loaded upfront |
|
||||
|
||||
```bash
|
||||
ENABLE_TOOL_SEARCH=auto:5 claude # 5% threshold
|
||||
ENABLE_TOOL_SEARCH=false claude # Disable
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MCP Output Limits
|
||||
|
||||
- Warning threshold: 10,000 tokens
|
||||
- Default max: 25,000 tokens
|
||||
- Configure with: `MAX_MCP_OUTPUT_TOKENS=50000`
|
||||
|
||||
---
|
||||
|
||||
## Using MCP Resources
|
||||
|
||||
Reference resources with `@` mentions:
|
||||
|
||||
```
|
||||
> Can you analyze @github:issue://123 and suggest a fix?
|
||||
> Compare @postgres:schema://users with @docs:file://database/user-model
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Using MCP Prompts as Commands
|
||||
|
||||
MCP prompts become available as `/mcp__servername__promptname` commands:
|
||||
|
||||
```
|
||||
> /mcp__github__list_prs
|
||||
> /mcp__github__pr_review 456
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dynamic Tool Updates
|
||||
|
||||
Claude Code supports MCP `list_changed` notifications, allowing servers to dynamically update available tools without reconnecting.
|
||||
|
||||
---
|
||||
|
||||
## Claude Code as MCP Server
|
||||
|
||||
```bash
|
||||
claude mcp serve
|
||||
```
|
||||
|
||||
Claude Desktop config:
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"claude-code": {
|
||||
"type": "stdio",
|
||||
"command": "claude",
|
||||
"args": ["mcp", "serve"],
|
||||
"env": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Plugin-provided MCP Servers
|
||||
|
||||
Plugins can bundle MCP servers in `.mcp.json` at plugin root or inline in `plugin.json`. Servers start automatically when plugin is enabled. Use `${CLAUDE_PLUGIN_ROOT}` for plugin-relative paths.
|
||||
|
||||
---
|
||||
|
||||
## Managed MCP Configuration (Enterprise)
|
||||
|
||||
### Option 1: Exclusive Control - managed-mcp.json
|
||||
|
||||
Deploy to system directory:
|
||||
- macOS: `/Library/Application Support/ClaudeCode/managed-mcp.json`
|
||||
- Linux/WSL: `/etc/claude-code/managed-mcp.json`
|
||||
- Windows: `C:\Program Files\ClaudeCode\managed-mcp.json`
|
||||
|
||||
Users cannot add/modify/use any servers not in this file.
|
||||
|
||||
### Option 2: Policy-Based Control
|
||||
|
||||
Use `allowedMcpServers` and `deniedMcpServers` in managed settings. Supports restriction by:
|
||||
- Server name (`serverName`)
|
||||
- Command (`serverCommand`) - exact match
|
||||
- URL pattern (`serverUrl`) - supports wildcards with `*`
|
||||
|
||||
Denylist takes absolute precedence over allowlist.
|
||||
|
||||
---
|
||||
|
||||
## Configuration File Locations
|
||||
|
||||
| Scope | Location |
|
||||
|-------|----------|
|
||||
| User + Local MCP | `~/.claude.json` |
|
||||
| Project MCP | `.mcp.json` (project root) |
|
||||
| General local settings | `.claude/settings.local.json` (project dir) |
|
||||
| Managed MCP | System directories (see above) |
|
||||
|
||||
---
|
||||
|
||||
## Tips
|
||||
|
||||
- Use `--scope` flag: `local` (default), `project` (shared), `user` (global)
|
||||
- Set env vars with `--env KEY=value`
|
||||
- Configure startup timeout: `MCP_TIMEOUT=10000 claude`
|
||||
- Use `/mcp` to authenticate with OAuth servers
|
||||
- Use `/mcp` to reconnect to servers
|
||||
@@ -23,7 +23,6 @@ Param(
|
||||
[string]$Domain,
|
||||
[string]$User,
|
||||
[switch]$UseLocalSystem,
|
||||
[int]$PublishTimeoutSeconds = 180,
|
||||
[int]$ServiceStopTimeoutSeconds = 30,
|
||||
[int]$ServiceStartTimeoutSeconds = 30
|
||||
)
|
||||
@@ -218,6 +217,7 @@ function Create-Service($name, $bin, $urls, [PSCredential]$credential, [bool]$us
|
||||
}
|
||||
# Set recovery to restart on failure
|
||||
sc.exe failure $name reset= 86400 actions= restart/60000/restart/60000/restart/60000 | Out-Null
|
||||
sc.exe description $name 'PEP nesting data API service' | Out-Null
|
||||
}
|
||||
|
||||
function Start-ServiceSafe($name) {
|
||||
|
||||
Reference in New Issue
Block a user