Sign in to follow this  
SlaveCam

NetHook CoolantParams

Recommended Posts

Hi,

There are currently no examples for this. How do I set CoolantParams for a Mastercam.Database.Operation so that

  • Coolant 1-3 are ON
  • Coolant 1 is BEFORE
  • Coolant 2 is WITH
  • Coolant 3 is AFTER

The following code sets ON and BEFORE to *all* coolant options

				var cool = new Mastercam.Operations.Types.CoolantParams()
				{
					Positions = new Mastercam.Operations.Types.CoolantPosition(Mastercam.Operations.Types.CoolantPositionType.Before),
					States = new Mastercam.Operations.Types.CoolantState(Mastercam.Operations.Types.CoolantStateType.On)
				};
				op.Coolant = cool;

and I really can't find a way to set them individually as the interface is very confusing. Thanks for help.

2019.

EDIT: As usual, found out the solution a few minutes after posting. Have to use the indexers (which I had completely missed)

			cool.Positions[0] = Mastercam.Operations.Types.CoolantPositionType.Before;
				cool.States[0] = Mastercam.Operations.Types.CoolantStateType.On;
				cool.Positions[1] = Mastercam.Operations.Types.CoolantPositionType.With;
				cool.States[1] = Mastercam.Operations.Types.CoolantStateType.On;
				cool.Positions[2] = Mastercam.Operations.Types.CoolantPositionType.After;
				cool.States[2] = Mastercam.Operations.Types.CoolantStateType.On;

 

 

Share this post


Link to post
Share on other sites

Back to this thing...

Because Nethook  API (2019) doesn't allow setting canned text coolant for tool, I had to resort to C-Hook API and to be honest, it is quite overwhelming.

a) How do I get tool (TlTool) using data in operation structutre?

b) How are operation's coolant values defined (not the old style coolant)?

void UpdateToolCoolantFromOperation(long opID)
{
	CInterrogateMastercamFile interrogator;
	auto libOp = interrogator.LoadForSingleOperation(opID, false);
	const operation* op = libOp->GetOpPtr();

/*
TlToolMill:
	void SetCannedTxtCoolant (const short *cool);
	void SetCannedTxtCoolant (const std::vector<short> &cool);

TlOpParams:
	void SetCannedTxtCoolant (const std::vector<short> &value);
	PROPERTY (Coolant, TlCoolant, SHARED_PTR) = std::make_shared<TlCoolant> ();
*/

	op = TpMainOpMgr.GetMainOpList().OpByID(opID); // Should I use this or interrogator?
	if (op != nullptr)
	{
		Cnc::Tool::TlMgrPtr mgr = interrogator.GetpToolMgr();
		// Where do I go from here?
	}
	

}

Any help is really appreciated. I'm not going to figure this out on my own, at least in a while..

Share this post


Link to post
Share on other sites
10 hours ago, SlaveCam said:

op = TpMainOpMgr.GetMainOpList().OpByID(opID); // Should I use this or interrogator? if (op != nullptr) { Cnc::Tool::TlMgrPtr mgr = interrogator.GetpToolMgr(); // Where do I go from here? }

GetMainOpList is fine, here is an example of retrieving the data from the operations and their tools :

//=======================   Next Region   ======================//

#pragma region Machine Group Functions

op_group* GetActiveMachineGroup()
{
	return  OMgetActiveMachineGroup(false);
}
bool VerifyMachineGroup()
{
	auto machGroup = GetActiveMachineGroup();
	if (machGroup && (machGroup->product == PRODUCT_MILL || machGroup->product == PRODUCT_ROUTER))
	{
		return true;
	}
	else
	{
		CString msg, title;
		msg.Format(_T("No Machine Group Detectes."));
		title.Format(_T("Bail!"));
		MessageBox(get_MainFrame()->GetSafeHwnd(), msg, title, MB_OK | MB_ICONERROR);
		return false;
	}

	return true;
}

#pragma endregion

//=======================   Next Region   ======================//

#pragma region Operation Manager Functions

//get a list of all the operations in the database
std::vector<operation *> GetListOfOperations()
{
	//vector to hold operations
	std::vector<operation *> ops;
	//check if we have something
	if (!TpMainOpMgr.GetMainOpList().IsEmpty())
	{
		//loop through the list of operation
		for (auto index = 0; index < TpMainOpMgr.GetMainOpList().GetSize(); ++index)
		{
			//get the current operation
			auto op = TpMainOpMgr.GetMainOpList()[index];
			//check if the pointer is valid
			if (op != nullptr)
			{
				//add the operation
				ops.push_back(op);
			}
		}
	}
	return ops;
}
//get a list of tool assemblies from the database
std::vector<Cnc::Tool::TlAssemblyCPtr> GetListOfTools()
{
	//vector to hold assemblies
	std::vector<Cnc::Tool::TlAssemblyCPtr> toolassemblies;
	//check if we have something
	if (!Cnc::Tool::GetToolSystem()->GetAssemblies().empty())
	{
		//loop through the list of assemblies
		for (auto index = 0; index < Cnc::Tool::GetToolSystem()->GetAssemblies().size(); ++index)
		{
			//loop through the list of assemblies
			auto tool = Cnc::Tool::GetToolSystem()->GetAssemblies()[index];
			//check if the pointer is valid
			if (tool != nullptr)
			{
				//add the current assembbly
				toolassemblies.push_back(tool);
			}
		}
	}
	return toolassemblies;
}
//find the tool used in the operation
Cnc::Tool::TlAssemblyCPtr MatchOperationWithTool(std::vector<Cnc::Tool::TlAssemblyCPtr> &toolassemblies, operation *const &op)
{
	//loop through the list of tool assemblies
	for (const auto tool : toolassemblies)
	{
		//find the tool that matches the operation
		if (tool->GetSlot() == op->tl.slot)
		{

			//return the tool
			return tool;
		}
	}
}

#pragma endregion

//=======================   Next Region   ======================//
//implementation example write operation and tool data into the comment section of the operation
void GetOperationData()
{
	//bail if there is no active machine group
	if (!VerifyMachineGroup())
	{
		return;
    }

	auto ops = GetListOfOperations();
	//get the list of tool assemblies
	auto toolassemblies = GetListOfTools();
	//check if we have something
	if (!ops.empty() && !toolassemblies.empty())
	{
		//loop through the list of operations
		for (const auto op : ops)
		{
			//get the tool
			auto tool = MatchOperationWithTool(toolassemblies, op);
			//get some other information from the tool
			CString OperationInfo;

			OperationInfo.Format(_T(" TlLength :%lf Tldia :%lf Tlnum :%d RPM :%d Feed :%lf"), tool->GetStickout(), op->tl.dia, tool->GetMillTool()->GetToolNumber(), op->tl.rpm, op->tl.feed);
#if C_H_VERSION >= 2100 // Mastercam 2019 or later

			//write the information to the operation comment
			_tcscpy(op->comment, OperationInfo);
#else
			//write the information to the operation comment
			sprintf(op->comment, OperationInfo);
#endif
			bool succf;

			DB_LIST_ENT_PTR pointer = nullptr;
			//rewrite the operation
			operation_manager(op, OPMGR_REWRITE, &pointer, &succf);
		}
	}
}

 

  • Thanks 1

Share this post


Link to post
Share on other sites
41 minutes ago, byte me said:

//get the tool auto tool = MatchOperationWithTool(toolassemblies, op);

Once you have your tool assembly you can  get the mill tool

tool->GetMillTool()

//TiToolMillPtr

  • Thanks 1

Share this post


Link to post
Share on other sites

Are you trying to modify the operation's coolant?  If so, new style coolant is handled by canned text...

void OperationService::SetOperationCoolant(int opID)
{
	auto op = TpMainOpMgr.GetMainOpList().OpByID(opID);
	if (op != nullptr)
	{
		op->cantxt.cantxt[0] = -3101;
		op->cantxt.cantxt[1] = -4103;
		op->cantxt.cantxt[2] = -5105;

		DB_LIST_ENT_PTR dbPointer = nullptr;

		auto isSuccess = false;

		operation_manager(
			op,
			OPMGR_REWRITE,
			&dbPointer,
			&isSuccess);
	}
}

The values are a bit of a mystery to me but as far as I can tell...

  • The left most digit will be a 3,4, or 5 corresponding to before, with, after
  • The two right most digits are the coolant; 00 is coolant 1 off, 01 is coolant 1 on, 02 is coolant 2 off,  03 is coolant 2 on etc.

For example, -5105 would mean coolant 3 on, after.

Share this post


Link to post
Share on other sites
1 hour ago, Zaffin_D said:

The values are a bit of a mystery to me but as far as I can tell...

  • The left most digit will be a 3,4, or 5 corresponding to before, with, after
  • The two right most digits are the coolant; 00 is coolant 1 off, 01 is coolant 1 on, 02 is coolant 2 off,  03 is coolant 2 on etc.

For example, -5105 would mean coolant 3 on, after.

The tool class also says it has canned text parameters, perhaps I am misinterpreting this :

void OperationService::SetOperationCoolant(int opID)
{
	auto op = TpMainOpMgr.GetMainOpList().OpByID(opID);
	if (op != nullptr)
	{
		Cnc::Tool::TlAssemblyCPtr toolAssembly;

		Cnc::Tool::GetToolSystem()->Find(op->tl.slot, toolAssembly);

		std::vector<short> cool;

		cool.push_back(-3101);

		cool.push_back(-4103);

		cool.push_back(-5105);

		toolAssembly->GetMillTool()->SetCannedTxtCoolant(cool);

		DB_LIST_ENT_PTR dbPointer = nullptr;

		auto isSuccess = false;

		operation_manager(
			op,
			OPMGR_REWRITE,
			&dbPointer,
			&isSuccess);
	}
}

 

  • Thanks 1

Share this post


Link to post
Share on other sites
12 minutes ago, byte me said:

In that case you could also try this member function of the tool class :

 

Have you tested this?

I had the below function for setting a tool's coolant, but no matter what I do the coolant won't stick.

void OperationService::SetToolCoolant(int opID)
{
	auto op = TpMainOpMgr.GetMainOpList().OpByID(opID);
	if (op != nullptr)
	{
		auto toolSystem = Cnc::Tool::GetToolSystem();
		auto toolAssembly = Cnc::Tool::TlAssemblyCPtr();
		if (toolSystem->Find(op->tl.slot, toolAssembly))
		{
			if (toolAssembly->HasMainTool())
			{
				auto millTool = toolAssembly->GetMillTool();

				std::vector<short> cannedTextCoolant(20);

				cannedTextCoolant[0] = -3101;
				cannedTextCoolant[1] = -4103;
				cannedTextCoolant[2] = -5105;

				millTool->SetCannedTxtCoolant(cannedTextCoolant);

				toolSystem->Update(toolAssembly->Clone());
			}
		}
	}
}

 

I'm also totally wrong about the right most digits.  They do have something to do with on and off; new theory below.

  • 01 and 02 sets ON and OFF for Coolant 1 
  • 03 and 04 sets ON and OFF for Coolant 2 
  • ...skip a few...
  • 19 and 20 sets ON and OFF for Coolant 10 

So to set Coolant 5 to ON and Before, use -3109. 

  • Thanks 1

Share this post


Link to post
Share on other sites

Thank you both very much!! I just had many hours of hitting my head against wall, but at least figured out how to modify the tools.

I will try out the code above tomorrow and have no doubt that it works.

It took a while to figure out changes must be done on cloned object and they need to be reset for changes to take effect.

And in case it helps some other C-hook newbie

extern "C" __declspec(dllexport) void UpdateToolCoolantFromOperation(long opID)
{
	using namespace Cnc::Tool;

	const operation* op = TpMainOpMgr.GetMainOpList().OpByID(opID);
	if (op == nullptr)
		return;

	std::vector<TlAssemblyCPtr> assemblies = GetAssemblies();
	TlAssemblyCPtr opAssembly = FindAssemblyForOperation(assemblies, op);
	if (opAssembly == nullptr) return;	

	// Perform changes on cloned object
	TlAssemblyPtr newAssembly = opAssembly->Clone();

	TlToolMillPtr millTool = newAssembly->GetMillTool();
	if (millTool == nullptr) return;

	TlHolderPtr holder = newAssembly->GetMainHolder();
	if(holder != nullptr)
		holder->SetName(_T("Test holder"));

	//DebugBox(CString("Old name: ") + millTool->GetName());
	millTool->SetName(_T("Test mill tool"));
	millTool->SetToolNumber(123);

	newAssembly->SetName(_T("Test assembly")); // OK!
	//newAssembly->SetToolNumber(123); Will be overwritten by SetMainTool()

	TlCoolant tlCool; // 0 = ON, 1 = WITH
	tlCool.SetFloodState(0);
	tlCool.SetFloodTime(1); 
	tlCool.SetMistState(0); 
	tlCool.SetMistTime(1); 
	tlCool.SetToolState(0);
	tlCool.SetToolTime(1); 

	millTool->SetCannedTxtCoolant(tlCool); // TlCoolant is auto-converted to array

	// Must reset for changes to take effect
	newAssembly->SetMainTool(millTool);
	if(holder != nullptr)
		newAssembly->SetMainHolder(holder);

	// Update database
	if (GetToolSystem()->Update(newAssembly))
	{
		DebugBox(_T("OK"));
	}
}

 

  • Like 2

Share this post


Link to post
Share on other sites
26 minutes ago, Zaffin_D said:

Have you tested this?

I had the below function for setting a tool's coolant, but no matter what I do the coolant won't stick.

I didn't see a change when I ran the code, I don't even use coolant so I am unfamiliar.

I am pretty lost on this one..

Share this post


Link to post
Share on other sites
10 minutes ago, byte me said:

I didn't see a change when I ran the code, I don't even use coolant so I am unfamiliar.

I am pretty lost on this one..

SlaveCam got it.

You need to reset the main tool to the cloned assembly for the changes to stick.

void OperationService::SetToolCoolant(int opID)
{
	auto op = TpMainOpMgr.GetMainOpList().OpByID(opID);
	if (op != nullptr)
	{
		auto toolSystem = Cnc::Tool::GetToolSystem();
		auto toolAssembly = Cnc::Tool::TlAssemblyCPtr();
		if (toolSystem->Find(op->tl.slot, toolAssembly))
		{
			auto toolAssemblyClone = toolAssembly->Clone();

			if (toolAssemblyClone->HasMainTool())
			{
				auto millTool = toolAssemblyClone->GetMillTool();

				Cnc::Tool::TlCoolant tlCool;
				tlCool.SetFloodState(0);
				tlCool.SetFloodTime(1);
				tlCool.SetMistState(0);
				tlCool.SetMistTime(1);
				tlCool.SetToolState(0);
				tlCool.SetToolTime(1);

				millTool->SetCannedTxtCoolant(tlCool);

				toolAssemblyClone->SetMainTool(millTool);

				toolSystem->Update(toolAssemblyClone);
			}
		}
	}
}

The TlCoolant class is much more friendly than a vector.  Sadly I knew about it less than a year ago; my memory isn't what it used to be. 

Makes me think that there has to be a friendlier way to update the operation coolant.

  • Like 1

Share this post


Link to post
Share on other sites
2 minutes ago, Zaffin_D said:

SlaveCam got it.

You need to reset the main tool to the cloned assembly for the changes to stick.

Nice!

2 minutes ago, Zaffin_D said:

The TlCoolant class is much more friendly than a vector.  Sadly I knew about it less than a year ago; my memory isn't what it used to be.  Makes me think that there has to be a friendlier way to update the operation coolant.

Maybe, there seem to be a variety of ways to do the same thing when it comes to operations.Nice work guys!

Share this post


Link to post
Share on other sites

Hello folks.

This was a much better day (night) than yesterday. The functionality to update either tool's coolant from operation or vice versa is now finally ready..

Thank you both again for supporting code. What comes to canned text coolant magic numbers, Zeffen had it figured out. I made a quick summary of it:

BEFORE	= -31xx
WITH	= -41xx
AFTER	= -51xx

ON		= -xxnn, where nn = 01, 03,...,19
OFF		= -xxnn, where nn = 02, 04,...,20

ON/BEFORE
-3101
-3103
-3105
...
-3119

ON/WITH
-4101
-4103
-4105
...
-4119

ON/AFTER
-5101
-5103
-5105
...
-5119

OFF/BEFORE
-3102
-3104
-3106
...
-3120

OFF/WITH
-4102
-4104
-4106
...
-4120

OFF/AFTER
-5102
-5104
-5106
...
-5120
*/

BTW. It is easy to go wrong with TlCoolant, as if you input invalid values into it, there is no error checking.

Here's the code, could have better error messaging system (maybe later)

bool IsCoolantRelatedCannedText(short val)
{
	val = -val; // for readability
	return (val >= 3101 && val <= 3120) || (val >= 4101 && val <= 4120) || (val >= 5101 && val <= 5120);
}

// Reset tool's coolant using the given operation's coolant settings so that they are the same. Doesn't update database nor assembly.
void SetToolCoolantFromOp(Cnc::Tool::TlToolMillPtr tlTool, const operation* op)
{
	std::vector<short> opCool(MAX_CANTXT_SIZE); // TlCoolant constructor fails silently if too few elements
	const short* cant = op->cantxt.cantxt;

	// Each value must be checked because non-coolant related canned text will mess up TlCoolant
	int j = 0;
	for (int i = 0; i < MAX_CANTXT_SIZE; i++)
	{		
		if (IsCoolantRelatedCannedText(cant[i]))
			opCool[j++] = cant[i];
	}

	Cnc::Tool::TlCoolant tlCool(opCool);
	tlTool->SetCannedTxtCoolant(tlCool);
}

// Reset operation's coolant/canned text using the given tool's coolant settings so that they are the same. 
// Non-coolant related canned text are left intact. Doesn't update database.
// Returns true on success, false if the number of canned texts would exceed 20.
bool SetOpCoolantFromTool(operation* op, Cnc::Tool::TlToolMillCPtr tlTool)
{	
	short* cant = op->cantxt.cantxt;

	// Remove operation's coolant related canned texts.
	std::vector<short> opCool(cant, cant + MAX_CANTXT_SIZE);
	opCool.erase(std::remove_if(opCool.begin(), opCool.end(), IsCoolantRelatedCannedText), opCool.end());
	opCool.erase(std::remove(opCool.begin(), opCool.end(), 0), opCool.end());

	// Get coolant from tool
	std::vector<short> toolCool = tlTool->GetCannedTxtCoolant(); // Size is always 20
	toolCool.erase(std::remove(toolCool.begin(), toolCool.end(), 0), toolCool.end());

	if (toolCool.size() + opCool.size() > 20)
		return false; // Too many canned texts? (rare)

	// Reset op's canned text
	std::fill(cant, cant + MAX_CANTXT_SIZE, 0);
	std::copy(opCool.begin(), opCool.end(), cant);
	std::copy(toolCool.begin(), toolCool.end(), cant + opCool.size());
	return true;
}

// Make tool have same coolant settings as operation.
// Returns false if opID not found, operation has no milling tool or database update fails.
extern "C" __declspec(dllexport) bool UpdateToolCoolantFromOp(long opID)
{
	using namespace Cnc::Tool;

	const operation* op = TpMainOpMgr.GetMainOpList().OpByID(opID);
	if (op == nullptr)
		return false;

	TlAssemblyCPtr opAssembly = FindAssemblyOfOperation(op);
	if (opAssembly == nullptr) 
		return false;

	if (!opAssembly->HasMainTool())
		return false;

	TlAssemblyPtr newAssembly = opAssembly->Clone();
	TlToolMillPtr millTool = newAssembly->GetMillTool();
	if (millTool == nullptr) 
		return false;

	SetToolCoolantFromOp(millTool, op);
	newAssembly->SetMainTool(millTool);
	return GetToolSystem()->Update(newAssembly);
}

// Make operation have same coolant settings as tool. 
// Returns false if opID not found, operation has no milling tool or database update fails. 
// Returns false if number of canned texts with new coolant values would exceed 20.
extern "C" __declspec(dllexport) bool UpdateOpCoolantFromTool(long opID)
{
	using namespace Cnc::Tool;

	operation* op = TpMainOpMgr.GetMainOpList().OpByID(opID);
	if (op == nullptr)
		return false;

	TlAssemblyCPtr opAssembly = FindAssemblyOfOperation(op);
	if (opAssembly == nullptr)
		return false;

	if (!opAssembly->HasMainTool())
		return false;

	TlToolMillPtr millTool = opAssembly->GetMillTool();
	if (millTool == nullptr)
		return false;

	if (!SetOpCoolantFromTool(op, millTool))
		return false;

	DB_LIST_ENT_PTR dbPointer = nullptr;
	bool isSuccess = false;

	// Requires header m_mill.h and library McMill.lib
	operation_manager(
		op,
		OPMGR_REWRITE,
		&dbPointer,
		&isSuccess);

	return isSuccess;
}

 

  • Like 2

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

Join us!

eMastercam - your online source for all things Mastercam.

Together, we are the strongest Mastercam community on the web with over 56,000 members, and our online store offers a wide selection of training materials for all applications and skill levels.

Follow us