Giter VIP home page Giter VIP logo

cfx's People

Contributors

ahanslovsky avatar alexisfouqueteuroplacer avatar asmcord avatar brianworrall avatar canavisia avatar danieleasm avatar dependabot[bot] avatar dhanya-tk avatar engrx2019 avatar flex-altmraut avatar johnjwalls avatar johnjwallsiii avatar njkowlski avatar pantoast avatar roberthudjakov avatar sarumathigetech avatar simon-smith avatar siox0911 avatar tematt avatar thomasbaechlerconti avatar timburke avatar viscomlr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cfx's Issues

Abilty of CFX to transfer unique board info like MAC address, device firmware, etc.

I am an applications engineer not a developer so please bear with me.

On our test equipment we currently are able to create custom routines that, after successful validation of a UUT serial number, can download from the customer's MES system unique items like a MAC address or firmware to be programmed into the UUT at test. The validation and download of anything unique is completely custom, based on the customer's MES implementation and their needs.

So I'm wondering when a customer moves to an IPC-CFX implementation, does CFX allow for transmission of this kind of data, either as part of a successful validation or as a separate action taken after a successful validation. As I imagine that CFX would be the sole messaging mechanism with the MES system, I do not envision using a custom app outside of CFX doing this.

I just wonder if the standard allows for this somehow.

Help with consuming large messages with CFX and generating an exception

Hi,

I need help consuming large messages using CFX library.
Using the CFX Channel subscription to get messages, I got an exception in my CFX software:
I/O: Amqp.AmqpException: Invalid frame size:993259, maximum frame size:262144.
The message was not consumed.

It seems the amqp.Net library, CFX is using, has a default message size value: DefaultMaxFrameSize = 256 * 1024
And a message I tried to consume is 993259 bytes large;
I tried to set AmqpCFXEndpoint.MaxFrameSize = 1048576;
But it has no effect on the MaxFrameSize of Amqp.Net;
It seems setting AmqpCFXEndpoint.MaxFrameSize has no effect whatsoever;
It seems also this limit apply to receive buffer size only;

Is there a standard in CFX to break down a message in several pieces ?

Here is where the exception is thrown:
// amqpnetlite\src\Net\AsyncPump.cs
` public async Task PumpAsync(uint maxFrameSize, Func<ProtocolHeader, bool> onHeader, Func<ByteBuffer, bool> onBuffer)

            await this.ReceiveBufferAsync(header, 0, FixedWidth.UInt).ConfigureAwait(false);
            int frameSize = AmqpBitConverter.ReadInt(header, 0);
            if ((uint)frameSize > maxFrameSize)
            {
                throw new AmqpException(ErrorCode.InvalidField,
                    Fx.Format(SRAmqp.InvalidFrameSize, frameSize, maxFrameSize));
            }

            ByteBuffer buffer = this.bufferManager.GetByteBuffer(frameSize);

`

And here is how I found a way to increase the maximum frame size in order to read the big message:
What do you think of it ?

`// The code in my software:
theEndpoint = new AmqpCFXEndpoint();
theEndpoint.Open(cfxHandle);
AmqpCFXEndpoint.MaxFrameSize = 1048576;

// CFX\Transport\AmqpConnection.cs
public void OpenConnection()
{
Cleanup();

        Exception connectException = null;

        try
        {
            Open o = new Open()
            {
                ContainerId = Endpoint.CFXHandle != null ? Endpoint.CFXHandle : Guid.NewGuid().ToString(),
                HostName = VirtualHostName
            };

            ConnectionFactory factory = new ConnectionFactory();
            if (this.NetworkUri.Scheme.ToUpper() == "AMQPS") factory.SSL.RemoteCertificateValidationCallback = ValidateServerCertificate;
            if (string.IsNullOrWhiteSpace(this.NetworkUri.UserInfo)) factory.SASL.Profile = SaslProfile.Anonymous;

            // Assigning CFX MaxFrameSize to AMQP MaxFrameSize and thus enabling reception of messages larger than Amqp default: 256 * 1024 bytes
            factory.AMQP.MaxFrameSize = Convert.ToInt32(AmqpCFXEndpoint.MaxFrameSize);

            Task<Connection> t = factory.CreateAsync(new Address(NetworkUri.ToString()), o, null);
            t.Wait(5000);
            if (t.Status != TaskStatus.RanToCompletion)
            {
                throw new Exception("Timeout on CreateAsync");
            }
            connection = t.Result;

            connection.Closed += AmqpObject_Closed;
            session = new Session(connection);
            session.Closed += AmqpObject_Closed;
        }
        catch (Exception ex)
        {
            connectException = ex;
            Debug.WriteLine(ex.Message);
            Cleanup();
        }

        if (connectException != null)
        {
            Cleanup();
            throw connectException;
        }
    }

`

Request to an unreachable device

Hi everybody,

The CFX SDK allows to configurate the timeout for a request (default value is 30 seconds). When I set it to, for example 3 seconds, it works when the PC that I try to reach is ON (with the software which is supposed to answer to the request not launched). It only waits for 3 seconds in this case, as wanted.

But if the PC is OFF, the configurated timeout is not working and I have to wait for about 40 seconds to go out of the ExecuteRequest() function.

Has anyone encountered the same issue? I'm afraid it's probably an AMQP issue but we have experts here and I hope there is a solution! ;)

Thanks!

Alexis

Cannot get the send receive to work.

I've been fighting with this issue for a little while now so hopefully, somebody here can help me.
I've tried following the tutorial available on the connectedfactory but I must be doing something wrong.

Here is what I have:
Send:
`
private void send(object sender, RoutedEventArgs e)
{
AmqpCFXEndpoint endpoint = new AmqpCFXEndpoint();
endpoint.Open("Vendor1.Model1.Machine34");

        // Encode your username and password into the destination Uri
        string username = "newadmin";
        string password = "s0m3p4ssw0rd";
        string hostname = "192.168.1.52";

        //  eg.  amqps://myusername:[email protected]
        Uri uri = new Uri(string.Format("amqps://{0}:{1}@{2}", username, password, hostname));

        // Target exchange on broker (shown here in RabbitMQ compatible format)
        string amqpTarget = "/exchange/CFXExchange";
        endpoint.AddPublishChannel(uri, amqpTarget);

        string targetEndpointHostname = "192.168.1.52";
        string targetCFXHandle = "Vendor2.Model2.Machine55";
        string remoteUri = string.Format("amqp://{0}", targetEndpointHostname);

        // Set a timeout of 20 seconds.  If the target endpoint does not
        // respond in this time, the request will time out.
        AmqpCFXEndpoint.RequestTimeout = TimeSpan.FromSeconds(20);

        // Build a GetEndpointInfomation Request
        CFXEnvelope request = CFXEnvelope.FromCFXMessage(new WhoIsThereRequest()
        {
            
        });
        request.Target = amqpTarget;
        CFXEnvelope response = endpoint.ExecuteRequest(remoteUri, request);
    }

`

Receive:
`
private void open(object sender, RoutedEventArgs e)
{
AmqpCFXEndpoint endpoint = new AmqpCFXEndpoint();
endpoint.Open("Vendor2.Model2.Machine55");

        // Encode your username and password into the destination Uri
        string username = "newadmin";
        string password = "s0m3p4ssw0rd";
        string hostname = "192.168.1.52";

        //  eg.  amqps://myusername:[email protected]
        Uri uri = new Uri(string.Format("amqps://{0}:{1}@{2}", username, password, hostname));

        // Source queue on broker (shown here in RabbitMQ compatible format)
        string amqpSource = "/queue/CFXQueque";
        endpoint.OnRequestReceived += Endpoint_OnRequestReceived;
        endpoint.AddSubscribeChannel(uri, amqpSource);


    }
    private CFXEnvelope Endpoint_OnRequestReceived(CFXEnvelope request)
    {
        // Encode your username and password into the destination Uri
        string username = "newadmin";
        string password = "s0m3p4ssw0rd";
        string hostname = "192.168.1.52";

        //  eg.  amqps://myusername:[email protected]
        Uri myRequestUri = new Uri(string.Format("amqps://{0}:{1}@{2}", username, password, hostname));
        string myCFXHandle = "Vendor2.Model2.Machine55";

        // Process request.  Return Result.
        if (request.MessageBody is WhoIsThereRequest)
        {
            CFXEnvelope result = CFXEnvelope.FromCFXMessage(new WhoIsThereResponse()
            { CFXHandle = myCFXHandle, RequestNetworkUri = myRequestUri.ToString(), RequestTargetAddress = "" });
            result.Source = myCFXHandle;
            result.Target = request.Source;
            return result;
        }

        return null;
    }

`

I see the messages are received by the AMQP ( see img )
Capture

Any help would be appreciated

How does the communication works?

Hello together

At first sorry for my expandable english...

For my understanding:
I will etablish CFX between a MES (in the first step as simulator) and a machine throw RabbitMQ. I have a running RabbitMQ server instance . I have created an exchange called "CFXExchange". I have created a queue called "werkbuch". I have bounded the queue "werkbuch" to the "CFXExchange".

The CFXExchange is configured as "Fanout". This works like a broadcasting message. If I send a message to this Exchange it will post the message to all queues which are binded.

Are all Endpoints in CFX a Queue in RabbitMQ?
Sends the Endpoint like a machine a broadcast message to an Exchange?
Sends the Endpoint like a MES a message directly to a Queue?

Whats the missing link between CFXHandle an ??? in RabbitMQ?

I was going through the tutorial in RabbitMQ and now I understand (basics) the communication in RabbitMQ. But how I have to do to start the implementation of CFX in my plant?

Can everyone help me to build a big picture in my head?

ExecuteRequest throws "Unexpected character encountered while parsing value: . Path '', line 0, position 0"

Hello,

When calling ExecuteRequest, the following JSON parse exception is thrown:

ERROR MESSAGE: Unexpected character encountered while parsing value: �. Path '', line 0, position 0.
at CFX.Transport.AmqpCFXEndpoint.d__138.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at CFX.Transport.AmqpCFXEndpoint.ExecuteRequest(String targetUri, CFXEnvelope request)
at CGC.HellerRecipeExtractor.Service.CFXController.Connect() in.....

I'm running RabbitMQ 3.8.12 locally with amqp1.0 plugin enabled. I'm trying to retrieve the recipe running on a Heller oven. The Heller CFX app and my .NET app are all running locally. I created a new exchange called "Heller".

Below is the code to create the envelope and call ExecuteRequest - taken from the Demo app on GitHub.

CFXEnvelope env = new CFXEnvelope()
{
    Source = MyEndpoint.CFXHandle,
    Target = hellerHandle,
    MessageBody = new  AreYouThereRequest()
    {
        CFXHandle = myHandle
    }
};

env.Source = myHandle;
env.Target = hellerHandle;
CFXEnvelope response = null;

try
{
    response = MyEndpoint.ExecuteRequest(hellerUri, env);
}
catch (Exception x)
{
    logger.Error($"ERROR OCCURRED MAKING REQUEST TO {hellerUri}, handle {hellerHandle}.\nERROR MESSAGE:  {x.Message} \n{x.StackTrace}");
}

Here's the CFX log:

Info: 2021-03-02T09:38:27.6207836+00:00 Connecting to amqp://localhost:5672/
SEND AMQP 3 1 0 0
SEND AMQP 3 1 0 0
SEND AMQP 3 1 0 0
Info: 2021-03-02T09:38:27.6478469+00:00 Connected to amqp://localhost:5672/. Establishing Links...
RECV sasl-mechanisms(sasl-server-mechanisms:[ANONYMOUS,AMQPLAIN,PLAIN])
RECV AMQP 0 1 0 0
RECV AMQP 0 1 0 0
SEND AMQP 0 1.0.0
SEND (ch=0) begin(remote-channel:0,next-outgoing-id:4294967293,incoming-window:2048,outgoing-window:2048,handle-max:63)
RECV (ch=0) attach(name:/exchange/Heller,handle:0,role:True,snd-settle-mode:Unsettled,rcv-settle-mode:First,source:source(durable:0,timeout:0,dynamic:False),target:target(address:/exchange/Heller,durable:0,timeout:0,dynamic:False),incomplete-unsettled:False,initial-delivery-count:0,max-message-size:0)
SEND (ch=0) attach(name:/exchange/Heller,handle:0,role:False,snd-settle-mode:Unsettled,rcv-settle-mode:First,source:source(durable:0,timeout:0,dynamic:False),target:target(address:/exchange/Heller,durable:0,timeout:0,dynamic:False),incomplete-unsettled:False,initial-delivery-count:0,max-message-size:0)
RECV (ch=0) begin(remote-channel:0,next-outgoing-id:0,incoming-window:65535,outgoing-window:65535,handle-max:63)
RECV (ch=0) flow(next-in-id:4294967293,in-window:65535,next-out-id:0,out-window:65535,handle:0,delivery-count:0,link-credit:65536,available:0,drain:False,echo:False)
RECV sasl-outcome(code:Ok)
Debug: 2021-03-02T09:38:27.6548654+00:00 sender-/exchange/Heller Enqueuing 1 messages.
RECV (ch=0) open(container-id:rabbit@MyWorkStation,max-frame-size:250000,channel-max:0,idle-time-out:60000,properties:[cluster_name:rabbit@MyWorkStation,copyright:Copyright (c) 2007-2021 VMware, Inc. or its affiliates.,information:Licensed under the MPL 2.0. Website: https://rabbitmq.com,platform:Erlang/OTP 23.2.6,product:RabbitMQ,version:3.8.12])
Debug: 2021-03-02T09:38:27.7792208+00:00 sender-/exchange/Heller Triggering Processing...
Debug: 2021-03-02T09:38:31.9063537+00:00 sender-/exchange/Heller Attempting to process queued messages...
Debug: 2021-03-02T09:38:33.7618217+00:00 GZIP Compressed Message(s) of Size 346 bytes to 250 bytes
Debug: 2021-03-02T09:38:33.7628243+00:00 GZIP Compressed Message(s) of Size 395 bytes to 283 bytes
SEND AMQP 3 1 0 0
RECV sasl-mechanisms(sasl-server-mechanisms:[ANONYMOUS])
SEND sasl-init(mechanism:ANONYMOUS,initial-response:...)
RECV sasl-outcome(code:Ok)
RECV AMQP 0 1 0 0
RECV (ch=0) begin(remote-channel:0,next-outgoing-id:0,incoming-window:2048,outgoing-window:2048,handle-max:63)
RECV (ch=0) open(container-id:ContainerHost-4f7aacdec80a4807bca6d630e283aad4,host-name:10.162.14.104,max-frame-size:262144,channel-max:255,idle-time-out:2147483647)
SEND (ch=0) attach(name:request-receiver,handle:0,role:True,snd-settle-mode:Unsettled,rcv-settle-mode:First,source:source(address:Heller.Reflow.1707-Line,durable:0,timeout:0,dynamic:False),target:target(address:CGControls.Heller.RecipeExtractor,durable:0,timeout:0,dynamic:False),incomplete-unsettled:False,initial-delivery-count:0,max-message-size:0)
SEND (ch=0) begin(remote-channel:0,next-outgoing-id:4294967293,incoming-window:2048,outgoing-window:2048,handle-max:63)
SEND (ch=0) flow(next-in-id:0,in-window:2048,next-out-id:4294967293,out-window:2048,handle:0,delivery-count:0,link-credit:300,available:0,drain:False,echo:False)
SEND AMQP 0 1.0.0
SEND (ch=0) attach(name:CGControls.Heller.RecipeExtractor,handle:1,role:False,snd-settle-mode:Unsettled,rcv-settle-mode:First,source:source(durable:0,timeout:0,dynamic:False),target:target(address:Heller.Reflow.1707-Line,durable:0,timeout:0,dynamic:False),incomplete-unsettled:False,initial-delivery-count:0,max-message-size:0)
SEND (ch=0) open(container-id:AMQPNetLite-201dc026,host-name:10.162.14.104,max-frame-size:262144,channel-max:255,idle-time-out:2147483647)
RECV (ch=0) attach(name:request-receiver,handle:0,role:False,snd-settle-mode:Unsettled,rcv-settle-mode:First,source:source(address:Heller.Reflow.1707-Line,durable:0,timeout:0,dynamic:False),target:target(address:CGControls.Heller.RecipeExtractor,durable:0,timeout:0,dynamic:False),incomplete-unsettled:False,initial-delivery-count:0,max-message-size:0)
RECV (ch=0) attach(name:request-receiver,handle:0,role:False,snd-settle-mode:Unsettled,rcv-settle-mode:First,source:source(address:Heller.Reflow.1707-Line,durable:0,timeout:0,dynamic:False),target:target(address:CGControls.Heller.RecipeExtractor,durable:0,timeout:0,dynamic:False),incomplete-unsettled:False,initial-delivery-count:0,max-message-size:0)
RECV (ch=0) attach(name:CGControls.Heller.RecipeExtractor,handle:1,role:True,snd-settle-mode:Unsettled,rcv-settle-mode:First,source:source(durable:0,timeout:0,dynamic:False),target:target(address:Heller.Reflow.1707-Line,durable:0,timeout:0,dynamic:False),incomplete-unsettled:False,initial-delivery-count:0,max-message-size:0)
SEND (ch=0) transfer(handle:0,delivery-id:0,delivery-tag:00000001,message-format:0,settled:False,more:False,rcv-settle-mode:First,resume:False,aborted:False,batchable:False) payload 554
SEND (ch=0) transfer(handle:1,delivery-id:0,delivery-tag:00000001,message-format:0,settled:False,more:False,rcv-settle-mode:First,resume:False,aborted:False,batchable:False) payload 553
RECV (ch=0) disposition(role:True,first:0,last:0,settled:True,state:accepted(),batchable:False)
Debug: 2021-03-02T09:38:33.8395512+00:00 sender-/exchange/Heller 1 messages transmitted. 0 messages remaining in spool.
RECV (ch=0) disposition(role:True,first:0,last:0,settled:True,state:accepted(),batchable:False)
RECV (ch=0) close(error:error(condition:amqp:internal-error,description:Unexpected character encountered while parsing value: �. Path '', line 0, position 0.))
SEND (ch=0) close()
Error: 2021-03-02T09:38:33.8505540+00:00 Unexpected character encountered while parsing value: �. Path '', line 0, position 0.
Error: 2021-03-02T09:38:33.8575720+00:00 at Amqp.ReceiverLink.ReceiveInternal(MessageCallback callback, Int32 timeout) in C:\Users\mqt\repo\amqpnetlite.rel\src\ReceiverLink.cs:line 472
at Amqp.ReceiverLink.Receive(TimeSpan timeout) in C:\Users\mqt\repo\amqpnetlite.rel\src\ReceiverLink.cs:line 235
at CFX.Transport.AmqpCFXEndpoint.d__138.MoveNext()
SEND (ch=0) detach(handle:0,closed:True)
RECV (ch=0) detach(handle:0,closed:False)

When is new nuget package generated?

I want to use GetMaterialInformationRequest and GetMaterialInformationResponse Messages but these are not yet packaged in nuget. Does CFX repo has any timeline for publishing nuget package?

Some clarification on request / response

I have a three part question about responses.

  1. I assume if an MES system wanted to perform a WhoIsThereRequest, it would publish to a channel that all the machine endpoints are subscribed to. Is this correct? If so, would the machines just publish a response to a channel that the MES system subscribes to? Or is there a different way to respond to that query.

  2. It appears ExecuteRequest is a direct link to an ad-hoc "amqp server" resident within the SDK (assuming a requestUri and a listener is added). So endpoint A initiates a direct ExectureRequest directly to endpoint B and the OnRequestReceived event is fired on endpoint B. How does endpoint B respond to the request? Does it just respond with it's own ExecuteRequest.

  3. Finally, what is the difference between these two events: OnRequestReceived versus OnCFXMessageReceivedFromListener.

Sending messages might lead to 5 seconds timeput when broker is offline

When sending a CFX message the AmqpConnection class calls the OpenConnection which is a synchrounous call. This itself is calling the Communication library, which is a asynchrounous call.
See code
Task t = factory.CreateAsync(new Address(NetworkUri.ToString()), o, null);
t.Wait(5000);
if (t.Status != TaskStatus.RanToCompletion)
{
throw new Exception("Timeout on CreateAsync");
}

This will lead to blocking calls when publishing messages whilce the broker is not reachable with an timeout of 5 seconds.

CFX for LabVIEW

Hi,

I am new to CFX standard and still trying to get a handle on the basics. I read through the CFX Demo and installed the SDK through NuGet Package available on Github. If I understand correctly the CFX SDK (a .Net library) is available that can be called in other software platforms. I am primarily a LabVIEW developer and want to implement CFX messaging through LabVIEW.

So far I have been trying to get the CFX Demo working from LabVIEW but I have not been able to connect to the host site. Maybe I am calling the wrong Properties/Methods. I was wondering if anyone here has used/called the SDK from LabVIEW and successful in getting the Demo to work. If yes, I would appreciate if you can share your LabVIEW code OR give suggestions to help me get through the issue.

Thanks,
Chetan

Can CFX support LDAP authentication?

Hi,

May I know if CFX support LDAP authentication to broker?

I am using the following code to establish a connection to the rabbitmq broker.

this.BrokerUri = new Uri($"amqp://{username}:{Uri.EscapeDataString(password)}@{hostname}:{port}");

it works when I am using RabbitMQ Client C# with LDAP backend enabled for rabbitMQ, but when I tried the same for CFX to establish a connection to the RabbitMQ broker.

It will return successfull at "endpoint.TestChannel" but

It throws error me the following error at the "endpoint.TestPublishChannel" and it will not allow to publish messages.

Reader error: {badmatch,
{error,
{'EXIT',
{{badmatch,
{error,
{{{badmatch,{error,{auth_failure,"Refused"}}},
[{rabbit_amqp1_0_session_process,init,1,
[{file,"src/rabbit_amqp1_0_session_process.erl"},
{line,52}]},
{gen_server2,init_it,6,
[{file,"src/gen_server2.erl"},{line,554}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,249}]}]},
{child,undefined,channel,
{rabbit_amqp1_0_session_process,start_link,
[{0,<0.2281.0>,<0.2286.0>,
{user,<<"snow.bunny">>,
[administrator,management],
[{rabbit_auth_backend_ldap,
{impl,"[email protected]",
<<"t@stSnowPassword">>}}]},
<<"/">>,249992,
{amqp_adapter_info,
{0,0,0,0,0,0,0,1},
5672,
{0,0,0,0,0,0,0,1},
4150,<<"[::1]:4150 -> [::1]:5672">>,
{'AMQP',"1.0"},
[{ssl,false}]},
<0.2283.0>}]},
intrinsic,30000,worker,
[rabbit_amqp1_0_session_process]}}}},
[{rabbit_amqp1_0_session_sup,start_link,1,
[{file,"src/rabbit_amqp1_0_session_sup.erl"},{line,53}]},
{supervisor2,do_start_child_i,3,
[{file,"src/supervisor2.erl"},{line,391}]},
{supervisor2,handle_call,3,
[{file,"src/supervisor2.erl"},{line,417}]},
{gen_server,try_handle_call,4,
[{file,"gen_server.erl"},{line,661}]},
{gen_server,handle_msg,6,
[{file,"gen_server.erl"},{line,690}]},
{proc_lib,init_p_do_apply,3,
[{file,"proc_lib.erl"},{line,249}]}]}}}}
[{rabbit_amqp1_0_reader,send_to_new_1_0_session,3,
[{file,"src/rabbit_amqp1_0_reader.erl"},{line,690}]},
{rabbit_amqp1_0_reader,handle_1_0_session_frame,3,
[{file,"src/rabbit_amqp1_0_reader.erl"},{line,467}]},
{rabbit_amqp1_0_reader,handle_1_0_frame,4,
[{file,"src/rabbit_amqp1_0_reader.erl"},{line,321}]},
{rabbit_amqp1_0_reader,recvloop,2,
[{file,"src/rabbit_amqp1_0_reader.erl"},{line,123}]},
{rabbit_reader,run,1,[{file,"src/rabbit_reader.erl"},{line,459}]},
{rabbit_reader,start_connection,4,
[{file,"src/rabbit_reader.erl"},{line,358}]},
{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,249}]}]

I am not sure what I am missing here that is causing me to get the error.
Any advise / guides will be appreciated.

Thank you.

Regards,
Snow Bunny.

CFX for NodeJS / Javascript

Is there an (unreleased) implementation of CFX for NodeJS / Javascript?
Especially for the AmqpCFXEndpoint class to provide request/response endpoints?
Thanks

De-panelization

In isnspection step customer wants to use AOI readed barcodes for de-panlization process for some products.
We need a way to send that trigger through CFX. Is there any suitable message for this purpose?

OverallResult PCBSelectiveSoldered

Hello,

I have seen that for example UnitsProcessed has a property "OverallResult", why PCBSelectiveSoldered does not have this property?

BR
Özgür

CFX Unable to consume messages from RabbitMQ queue.

Hi,

I am new in CFX and RabbitMQ.
I had followed the tutorial on both the CFX and also the RabbitMQ to publish and consume messages.

My broker is setup as follows.

  1. I had manually created my exchange, queue and bindings in RabbitMQ Broker =
    exchangeA -> routingKeyA -> queueA (Durable queue , without any additional arguments parameters included)

  2. CFX =
    Uri uri = new Uri($"amqp://{Username}:{Password}@localhost:5672");
    string exchangeAddress = $"/exchange/exhangeA/routingKeyA";
    string queueAddress = $"/queue/queueA/";

    endpoint.AddPublishChannel(uri,exchangeAddress);
    endpoint.AddSubscribeChannel(uri,queueAddress);

Result:

  1. I am able to publish and receive message using CFX successfully

However if I delete the queue and recreate it using the rabbitMQ management, and make it into a lazy queue by putting arguments with "x-queue-mode" = true, or enable auto-delete to true for the queue, my CFX is able to publish messages , but it is unable to consume messages from the queue.
An error message will keep showing that as follows:

"ERROR extablishing connection to queue = PRECONDITION_FAILED - inequivalent arg 'auto_delete' for queue 'queueA' in vhost '/': received 'false' but current is 'true'"

I had already set up the bindings for the queue and exchanges.

I would appreciate it if someone will kindly please guide me / let me know if there is a way to consume message from the queue , if the queue created in the RabbitMQ broker consist of arguments? Or currently CFX is unable to consume message from the queue if the queue was created with arguments, and it is only able to consume message from the queue which is durable without any arguments set?

Kindly please correct me if I am wrong.

Any feedback would be appreciated.

Thanking you in anticipation.
Regards,
Snow Bunny.

Database schema for CFX

Hi,

I am considering storing CFX Data in a database; Has someone done it already ?
I am interested mostly in the TestAndInspection class.
If it is the case, can he share a create script for it ?

Thank you

Subscribing to queue in CFXDemo broker

Hi,

I am trying to use the SDK to subscribe to an endpoint using AddSubscribeChannel(). It works with a local implementation of RabbitMQ, but not with the CFX Demo.
I get the error message: ACCESS_REFUSED to queue 'AegisCloud' for user 'guest'.
I guess I don't have the access rights to subscribe.
Is there a queue available with access rights for guest ?
What can be done to obtain a user with access rights to be able to test receiving messages ?
Thank you

Daniel SIRAN
ASTER Technologies

Are exclusive queues supported in CFX library?

Hi,

May I know if anyone knows how to make exclusive queues in the RabbitMQ broker when a connection is established using CFX library?

I would like the queue in the broker to be deleted automatically once the CFX connection is closed.

I know that it is possible if I am using RabbitMQ Client Library, but that also means that I have to establish a connection to the broker using the RabbitMQ client instead of the CFX library.

I would like to do the same but using CFX library. Is it possible?
I do not see any parameters in the CFX library which allows me to do that. May I know if exclusive queues are supported using CFX library?

Thanking you in anticipation.

Having a machine in CFX Demo List

I have already submitted a question about testing the online CFX Demo broker.
What should we do, at ASTER Technologies, to have a machine on the list ?
How can I test consuming messages from the online Aegis broker ?

No one answered. I addressed the message to Michael Ford, and got no answer.
At least tell me to whom should I address my request.

Chris, can you help ?

Thank you

Closing an Interrupted Connection

When an AmqpCFXEndpoint connection has been opened and the connection is Interrupted (the Endpoint_OnConnectionEvent recieves the "ConnectionEvent.ConnectionInturrepted"), you cannot close the connection via "endpoint.Close()"

When attempting to close it sends the event "ConnectionEvent.ConnectionFailed" and doesnt actually close the connection as far as im aware.

Is there a way to dispose of this connection in a more permanant fashion?

Setting up amqp v1.0 broker with rabbitMQ

I've set up amqp v1.0 broker by enable rabbitMQ plugin rabbitmq_amqp1_0.
At the broker side, error occurred when publish message with APEX CFX Demo Examples(or app) project.
The following is error message
handshake_error,running,<0.26804.0>,
{{symbol,"amqp:internal-error"},
"Session error: pnpn",
[function_clause,
[{rabbit_amqp1_0_framing,fill_from_binary,
[{'v1_0.amqp_value',undefined},

However, There is noting error when I used Qpid as producer.
Is anything missing at broker setting or APEX CFX Demo Examples project(or app) needs to be modified?

Durable Queue is storeing the cache file in the TEMP directory

The messages which are triggered to send which did not reach the broker are stored in a local file on the client. This file is stored in the TEMP directory. See code below.

public DurableQueue(string name)
: base()
{
dataName = System.IO.Path.GetTempPath();
dataName += (@"" + name + ".cache");
Initialize();
}
This might not be survive a reboot, because some customer computer polcies will clean the TEMP directory.

Can't connect to connected factory

Not sure if this is the place to ask this , but i'm having some trouble connecting the demo app to the connected facory. I've entered a unique Handle ( do i need to request one first? ) and the app seems to connect, yet i dont see any changes in the connected factory.

How to get the PCB partnumber ?

Hi,
In order for my software to retrieve and use PCB data such as CAD files after getting a UnitsInspected or UnitsTested, it needs a PartNumber.
One can find the board part number in the WorkOrder class. And a CFX.InformationSystem.WorkOrderManagement.WorkOrdersCreated message should be published to make available the data about a new board product being produced.
Then a CFX.Production.UnitsInitialized message should be published to make available the list of all the "PartNumber" units in production. The WorkOrderIdentifier referring to the previously published corresponding WorkOrder.
Ex:
"WorkOrderIdentifier": { "WorkOrderId": "WO45648798", "Batch": "BATCH45648798-1" }, "Units": [ { "UnitIdentifier": "UNIT5566687", "PositionNumber": 1, "PositionName": "CIRCUIT1", "X": 50.45, "Y": 80.66, "Rotation": 0.0, "FlipX": false, "FlipY": false }, { "UnitIdentifier": "UNIT5566688", "PositionNumber": 2, "PositionName": "CIRCUIT2", "X": 50.45, "Y": 80.66, "Rotation": 90.0, "FlipX": false, "FlipY": false } ]

So, here is my question: Is it the right/only way to connect the UnitIdentifier (SN) to the PCB PartNumber, publishing WorkOrdersCreated, UnitsInitialized and then for example UnitsInspected ?

Thank you

Clarification on Usage of AMQP 1.0 Headers for Content-Type and Encoding

Goal

The goal of this issue to help ensure that the CFX standard is able to support future message serialization formats and compression types easily without a danger to any existing client that may not support them. In order to enable this, there needs to be a clear way for a client to know the chosen serialization and compression format before trying to decode a message.

Overview

Currently the CFX SDK sends CFX messages serialized as JSON objects with optional deflate compression. The CFX standard calls out that future versions may support different (potentially nonjson) serialization formats and likely more compression algorithms on top of those underlying serialization formats.

Without a clear way to obtain the chosen compression/serialization formats from a received cfx message itself, it could be very difficult to safely allow multiple formats to coexist on the same broker since clients would have to guess what combination of serialization/compression was used for a given message.

AMQP 1.0 has standard properties to include these two values (content-type and encoding) in a globally understood way. Setting both properties now to valid MIME types will help ensure that future additions of other choices for either serialization format or compression will not negatively impact existing clients since they will be able to inspect the message properties and know how to decode it.

Details

The AMQP 1.0 protocol has a standardized way of communicating both serialization format using the content-type property and optional compression using the content-encoding property.

AMQP 1.0 defines that both content-type and content-encoding properties, when set should be valid MIME content-types.

Currently, the CFX SDK does not set content-type explicitly and sets content-encoding to a non-null value only when compressing, in which case it uses a nonstandard value CFX-COMPRESSED.

See: https://github.com/IPCConnectedFactoryExchange/CFX/blob/master/CFX/Transport/AmqpUtilities.cs#L66

The AMQP 1.0 standard specifies that content-encoding must be an IANA registered MIME type (see amqp 1.0 standard page 78).
image

Recommendations

The following is a list of potential ways to address the above described issue for consideration and disuccsion.

  1. Add a content-type header on all messages with MIME type application/json
  2. When compressing messages, change nonstandard MIME type from CFX-COMPRESSED to, for example, application/x-gzip.
  3. In the SDK, check content-type and content-encoding and validate their contents before decoding. This will allow clients to operate in a mixed encoding environment with clear error messages when receiving a message they are not able to decode (due to unknown serialization format or compression type)
  4. In the SDK accept an empty content-type header as a synonym for application/json to allow full backwards compatibility with legacy senders that do not set content-type correctly.
  5. In the SDK accept an value of CFX-COMPRESSED as a synonym for no-compression to allow full backwards compatibility with legacy senders that send a nonstandard content-encoding value. See https://github.com/IPCConnectedFactoryExchange/CFX/blob/master/CFX/Transport/AmqpUtilities.cs#L123

References

InspectionMethod have missing members

Hi,
Today, there are only 3 members in CFX.Structures InspectionMethod Enumeration:
Human, AOI, SPI
is AXI (Automatic X-ray Inspection) considered as AOI in CFX ?
And what about these methods of inspection?

  • ICT (In-Circuit Test)
  • FPT (Flying Probe Test)
  • FCT (Functional Circuit Test)
  • BST (Boundary-Scan Test (JTAG))
  • SMT P&P (component placement systems)

All these tests methods/machines should be able to send CFX.Production.TestAndInspection messages. Are they missing or is there another explanation ?
In the list of machines already registered in the online, CFX Demo, I can see AXI, ICT and SMT tests machines with no InspectionMethod to use.

Thank you

Daniel Siran
ASTER Technologies

Where is ResourceState.On / .Off defined?

I am attempting to implement the example code in LabVIEW (so apologies for the lack of .NET fluency), and when I look at sending a StationStateChanged message as shown on this page, I see NewState = ResourceState.On, OldState = ResourceState.Off.

In looking at the source for ResourceState I do not see On and Off defined.

Are these just assumed Boolean constants (On = 1 and Off = 0)?

Would it be poor practice to send a message about a Station State and not use one of the defined ResourceState enumerations?

Thanks!

MaterialsInstalled and MaterialsUninstalled

Hi,

The CFX.Production.Assembly.MaterialsInstalled and CFX.Production.Assembly.MaterialsUninstalled messages are defining the installed and uninstalled materials on a production unit.

But what about the "not installed" materials? (like for instance components rejected by vision test). It should be interisting to have a CFX.Production.Assembly.MaterialsNotInstalled message as it's different from the CFX.Production.Assembly.MaterialsUninstalled message, and it should fill the hole.

We are ready to code this message but we want to be sure that we understand those existing messages as they were designed.

Alexis FOUQUET.

WorkCompleted async response

Hi,
Currently, CFX WorkCompleted message has no response message described in CFX standard.
In our use case, when AOI sends "WorkCompleted" to MES interface, AOI operator should see feedback from MES. MES Response will contain information, how message processing ended in MES interface (Ok/Error)
What could be best CFX message to use for this purpose?

Recommendation to Set Application Headers on AMQP 1.0 Messages

Overview

Currently, the AMQP 1.0 serialization of CFX messages appears to consist of:

  1. Serializing the message to json source
  2. Inserting the message into a json envelope that contains the message topic, source, target, id and a few other fields. source
  3. Sending the envelope as an opaque message through the AMQP 1.0 protocol. source

This means that there is no information about the contents of the message available in a format that can be used to route or filter the messages based on, for example, topic.

Each machine can be configured to send all messages generated to a single fixed target address but, if that target is a message broker, there is no exposed information to allow the broker to route individual messages to different queues. An example use case would be:

There are two systems interested in different CFX messages. One system just wants placement data to show a realtime line dashboard. It is a small computer, perhaps a low-cost IoT linux device that expects to receive a low volume of CFX messages.

There is a second system that performs level 4 traceability and receives detailed reports of all components installed on each production unit.

As I understand it, there is no way currently to set up a single amqp 1.0 broker that would be able to receive all messages from a machine and route the performance topic only to system 1 and all messages to system 2.

As the size of CFX installations grow, the implicit use of fanout-only exchanges in this way could cause rapid resource need expansion or complex manually configuration of machines in order to have multiple targets with specific messages sent to each target. This latter setup partially negates the benefit of using a pub/sub compatible protocol like amqp 1.0 which inherently has a way to achieve this goal without needing multiple links to each machine.

The current issue blocking such a centralized cfx broker deployment is that the cfx message to amqp 1.0 mapping does not appear to include metadata like topic and cfx version in a way that the amqp broker can access to make routing decisiosn.

Potential Solution

This a potential solution to the above issue proposed here for discussion and brainstorming with the CFX team.

Include key information from the cfx envelope in the amqp 1.0 "application properties" section of the message. See amqp 1.0 Page 80.

This header section is reserved by amqp 1.0 for applications like cfx to include a key/value map of information that is designed to be used to route messages without parsing the message contents.

If, for example, the cfx message topic, source, target and cfx version were duplicated as application properties, then you would be able to route a subset of messages based on topic to a subset of consumers.

Benefits for on-premise RabbitMQ Deployments

RabbitMQ has a mapping of amqp 1.0 application headers to amqp 0.9.1 headers which allows them to be used with a rabbitmq header exchange to perform complex filtering and routing. By adding the cfx topic to application headers then users would be able to set up complex routing scenarios needed by large deployments with no backwards-compatibility implications.

See here

Benefits to Cloud Deployments

I believe that cloud amqp 1.0 compliant messaging systems also look at application headers to allow for programmatic routing. For example, Azure Service Bus maps application headers to User Properties (see here).

User Properties can be used to filter message subscriptions. (see here).

Bottom Line

Adding key information to the application properties section of the AMQP messages (in addition to placing it in the json envelope wrapper) will facilitate large CFX deployments since it permits brokers to route subsets of messages.

This benefit comes at no cost to point-to-point installations (or small fanout style exchanges) that do not need to worry about resource optimization.

Adding this information sooner rather than later can hopefully ensure that the majority of CFX implementations adopt it so that their messages can be routed in a manner other than point-to-point or fanout.

Are there instructions for settings up an amqp broker?

I would like to be able to host the amqp service myself, with something like RabbitMQ. Has anyone been able to use this with anything other than the amqp://cfx.aiscorp.com:5672 broker? I've tried setting settings up an exchange/queue that has similar naming, but none of the messages seem to come through. I'd appreciate any insight anyone could give me into this. Thanks!

How is the process interlock with barcode scanner done with CFX

Hi,
i have a question regarding the process interlock via barcode scanner with CFX. As soon as the barcode is read by the scanner, which CFX message should be used for sending this to the broker? Furthermore is there a response with the program to load or is the program load done separately by the broker with a load program call? If yes what is the name of the CFX request from the host to the equipment?
Thanks in advance for your answers.

Regards

Need more information for EndpointInformation Message

Hi,

I think we need PCB specification information in GetEndpointInformationResponse message.
And we also need software information in it.
So I recommend that we add the following in EndpointInformation.

"EndpointInformation" : {
... ...
"UnitSpecification" : {
"MaxUnitSize" : 100.0,
"MinUnitSize" : 30.0,
"MaxComponentHeight" : 10.0,
"MaxUnitWeight" : 100.0
},
"Software" : {
"SystemFirmware" : "PLC XXX AA 1.0",
"OperationSystem" : "Windows 7 Home Edition",
"SoftwareName" : "Printer Professional",
"SoftwareRevision" : "1.25"
}
}

Unable to publish Message using CFX.CFXSDK.Core

The following works on Forms (CFX.CFXSDK)


 AmqpCFXEndpoint.RequestTimeout = TimeSpan.FromSeconds(30);
            AmqpCFXEndpoint endpoint = new AmqpCFXEndpoint();
            endpoint.Open("MachineName");

            String Username = "sample";
            String Password = "sample";
            String Hostname = "localhost";
            String Port = "5672";
            Uri BrokerUri = new Uri($"amqp://{Username}:{Password}@{Hostname}:{Port}");
            String BrokerAddress = "/exchange/sample_exchange/sample_routingKey";  

            Exception exception = null;

            if (!endpoint.TestChannel(BrokerUri, out exception))
            {
                Console.WriteLine("ERROR: Unable to connect to RabbitMQ" + Environment.NewLine);
                Console.WriteLine($"URI = {BrokerUri}" + Environment.NewLine);
                Console.WriteLine($"ERROR MESSAGE = {exception.Message}" + Environment.NewLine);

                return;
            }
            else
            {
                Console.WriteLine("Connection To RabbitMQ broker Successful" + Environment.NewLine);
            }

            if (!endpoint.TestPublishChannel(BrokerUri, BrokerAddress, out exception))
            {
                Console.WriteLine("ERROR: Unable to establish connection to RabbitMQ Broker exchange" + Environment.NewLine);
                Console.WriteLine($"URI = {BrokerUri}" + Environment.NewLine);
                Console.WriteLine($"ADDRESS = {BrokerAddress}" + Environment.NewLine);
                Console.WriteLine($"ERROR MESSAGE = {exception.Message}" + Environment.NewLine);

                return;
            }
            else
            {
                Console.WriteLine("Connection to RabbitMQ broker exchange is successful." + Environment.NewLine);
            }

            endpoint.AddPublishChannel(BrokerUri, BrokerAddress);

            CFXEnvelope env = new CFXEnvelope()
            {
                MessageBody = new EndpointConnected()
                {
                    CFXHandle = "SampleCFXHandle",
                    RequestNetworkUri = "request URI",
                    RequestTargetAddress = "Sample MEssage to publish"
                }
            };

            endpoint.Publish(env);
            Console.WriteLine("Message had been published.");

But when I tried the same for Console version (CFX.CFXSDK.NetCore). The message is not published when I tried to run the application.

May I know if it uses a different approach to write the codes to publish the message if I am using CFX Core instead of using the CFX.CFXSDK?

Thank you.

Regards
Snow Bunny.

MTU Size and Message Fragmentation for Cloud Based Brokers

Background

Many cloud based amqp messaging layers such as Azure ServiceBus have a hard upper limit on maximum message site. For example Azure standard permits messages up to 256kb for standard tier and 1MB for a more expensive tier.

Given that CFX compliant machines natively send data via AMQP 1.0, it makes sense that a key future if not present deployment scenario would be to directly have the machines send their data to an AMQP 1.0 broker hosted, for example, on Azure. There are other cloud based services as well.

However, there's a potential blocking issue in that certain messages inside the CFX standard, specifically the test and inspection messages generated by SPI and AOI machines have a potentially unbounded size, even with compression because they list a CFX structure for every defect found or every measurement performed and there can be a large number of these entries, which in practice push the message size over the 256kb limit (upwards of 20-30MB without compression and even 2-3MB with gzip compression).

So, the question is, would it be feasible to define a "maximum message size" for CFX messages that we could always ensure messages stay within so they are feasible to send to a broker with fixed max message size. Given that the amount of data that needs to be sent is unchanged, this would imply a fragmentation scheme of some sort to split a single message across multiple AMQP messages, each under the maximum size.

This issue lays out options for achieving this with some discussion of pros/cons of each one.

Fragmentation Options

I see two major axes to decide on fragmentation and a third potential out-of-band option:

  1. Fragment before or after compression, i.e. fragment the json and then compress each message separately, or compress the message and then just split it across multiple messages.

    • fragment before compression would mean that each message can be decompressed independently but it would not be possible to predict the exact size of each message after compression until you compress them so it would be difficult to ensure you get each message just under the maximum limit for efficient.
    • fragment after compression would allow you to exactly split the message just under the size limit but would mean that the individual messages could not be decompressed until you first joined them together.
  2. Transport level or application level fragmentation.

    • transport level means that a single logical message is generated and it's roughly chopped into pieces but no piece makes sense without putting together all of the pieces first.
    • application level means that a single large message is split into multiple distinct messages such as a primary message with core details followed by "addendum messages" that contain the rest of the information in such a way that each message makes sense on its own and the combined set of messages contains the same information as the first message.
  3. Out of band transmission with inclusion of a unique pointer.

    In this option, no message is fragmented but for messages that could have large "extra data" like measurements or defect counts, there's a defined way to include a pointer to that data and a way to fetch it. For example, it could be that the message contains a unique URL in place of a large substructure (like the list of measurements in an aoi inspection report) where more data could be downloaded from another server out-of-band with the amqp messaging.

Design Considerations - transport level, fragment after compress

This section covers some of the implications of the various choices we might choose from above. In particular, I see the following major question:

Is it assumed that a given fragmented message will always be received by a single worker process in order? If this can be guaranteed, then fragmenting after compression is fine and transport level fragmentation is a good choice because we're basically just splitting a single message up and its going to be put back together on the other side of the link by a single worker with no ambiguity.

However if there is load balancing of messages where multiple messages for a single machine might be handled by multiple workers then having messages that can't be interpreted on their own is problematic because different worker processes may receive different fragments.

Since this is a cloud based system you would expect load balancing for scaleability but there could be a sticky association of messages from a single machine to a single worker that could allow this to work.

This would definitely be the simplest implementation:

  • take a message
  • compare to maximum size
  • while too large:
    • chop off the first max_size bytes and send as its own message
  • send the remaining message

You could mark each message in the amqp header with a Fragment N of M header to allow reconstruction.

Design Considerations - application level, fragment before compress

This option is predicated on a belief that there is value in being able to consider a "primary message" containing the "gist" of the event with subsequent addendum messages filling in details that not everyone may care about.

This could make sense, for example, for TestAndInspection AOI inspection reports:

  • the primary message would be the core inspection results (what was inspected, pass/fail).
  • the supplemental messages would be the detailed list of defects and measurements and you could imagine sending a number of such of "addendum inspection report" messages with as much detail as you want to include based on the maximum message size.

In this sense there is no fragmentation per se but rather just a clear understanding of which messages are fixed size vs flexible size and for those that are flexible size, the definition of addendum messages (which could be the same message but with a flag or field set to indicate they are addendums to a previous message) containing certain details.

Design Considerations - out of band data transfer

This is another alternative to the problem where there's an agreed upon set of ways to transfer "large amounts of data" that don't make sense to include in an amqp message. In that case what's included in the message is a unique pointer to fetch the large attachment from a different server that it was sent to out-of-band.

An example of how this could play out would be that:

  • the standard defines a way to send large files via http(s) post. They are posted with a unique url to a server whose address is part of the configuration of the machine.
  • for messages with large arrays of data, they can include a $external_url=URL key in place of the array data to indicate that it should be fetched from a 3rd party server.

Basically this would be the definition of a way to send files in addition to messages and a way to replace part of a message with a reference to an external file.

Pros/Cons

Given the 3 options, it's not clear to me which one stands out as a clear winner. Each one has pros and cons and makes sense given a particular view on how you expect the standard to be implemented.

Currently, I lean toward either the application level fragmenting with addendum messages or the out of band reference option but look forward to discussing more to see what could make the most sense.

Broadcast Request handling

Hi,

At this point, only one message is concerned by Broadcast Request (WhoIsThereRequest).
Is the current CFX code able to handle it?

The request function is defined like this :
public CFXEnvelope ExecuteRequest(string targetUri, CFXEnvelope request);

So it allows to only get one answer of one answering end point, not several.

Thanks for your feedback,

Alexis FOUQUET
R&D Software Engineer, EUROPLACER.

inboundHost = new ContainerHost(RequestUri); inboundHost object creation throws Exception : '((Amqp.Listener.IContainer)inboundHost).ServiceCertificate' threw an exception of type 'System.InvalidOperationException'

public void Open(string cfxHandle, Uri requestUri, X509Certificate2 certificate = null)
{
IsOpen = false;
if (string.IsNullOrEmpty(cfxHandle)) throw new ArgumentException("You must supply a CFX Handle");

        this.CFXHandle = cfxHandle;
        RequestUri = requestUri;

        **inboundHost = new ContainerHost(RequestUri);**

Auto Queue Binding

In the setup guide it states it is possible to bind queues to and Exchange within the CFX SDK.

Source: https://cfx.ipc.org/files/IPC-CFX-AMQP-Guide-v1_0.pdf
Page: 6

There is no indication that this is possible in the github source, im not sure if im missing something but it doesnt seem like it is possible to do this in the current SDK.

If this is not possible how are new machines or analizers expected to be added to a network or line? is it just manual?

PCBSelectiveSoldered to simple for our machines

Hi.
at the moment i am implementing PCBSelectiveSoldered in our project.

The problem is that the model is too simple for our machines.
First of all let me explain how our machines look like.

They can have multiple soldering stages, preheating stages and fluxing stages.
A soldering stage may have multiple axis systems. On an axis system there can be one or more soldering heads.
A flux stage may also have multiple axis systems. Each of them can have multiple bottles with different pressure and multiple flux heads with different consumption.

ZoneData not complex enough

The PCBSelectiveSoldered class has the property SolderedPCBs which is a list of SelectiveSolderedPCB. The SelectiveSolderedPCB class has the property ZoneData which is a list of ZoneData. The ZoneData look like this.

So if I get everything right, the idea is that for every stage the pcb went through, you create a ZoneData object and fill it with the data of the stage.

Some examples to explain the problem in my mind:

  • Let's assume a pcb went through a soldering stage. In this stage, there were two bath waves involved. That means there are 2 Bath_Temp values, but i can only set one. I could split that into two stages, but that somehow doesn't feel right, since it was actually just one stage.
  • There is a similar problem with the preheating stages. A preheater in our machine contains multiple segments. These segments have their own temperature and heating time (which can be different from segment to segment of one heater in the process). Again, I could split that into one stage per segment, but that would represent reality again because these segments don't heat the pcb after each other. Instead, they do it at the same time.

So what is the best solution for this? Should I split the phyiscal stages into seperate stages in the model? Should I just send the temperature of one bath, and ignore the values of the second bath?

For me, the best solution would be to adapt the models to allow more complex data. For example we could either make values like the Bath_Temp a list, or instead we could add a deeper level for data with some kind of SubStageSequence property. I would offer to implement it and create a PR. But first, i wanted to discuss the architecture.

HeaderData: Propertys that belong to stages

The PCBSelectiveSoldered class has the property HeaderData which is of type SelectiveSolderData. The SelectiveSolderData looks like this.

So when I understood that correctly, the idea is that for a soldered pcb, there is one single value of nitrogen flow (Nitrogen_Flow).
Again, in our machines, there are multiple of these values.

Naming of propertys

This is not a real problem but something strange. Why do the property names have an underscore in their name? Is there a reason for that?

We would offer to implement the changes if you don't have enough time for that right now

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.