OpenProtocolInterpreter 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package OpenProtocolInterpreter --version 1.0.0
NuGet\Install-Package OpenProtocolInterpreter -Version 1.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="OpenProtocolInterpreter" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add OpenProtocolInterpreter --version 1.0.0
#r "nuget: OpenProtocolInterpreter, 1.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install OpenProtocolInterpreter as a Cake Addin
#addin nuget:?package=OpenProtocolInterpreter&version=1.0.0

// Install OpenProtocolInterpreter as a Cake Tool
#tool nuget:?package=OpenProtocolInterpreter&version=1.0.0

OpenProtocolInterpreter

Build status License: MIT

OpenProtocol communication utility

Work in progress (AllRevisions):

  • Make lib understand all MID's revisions
  • Refactor the way to process the package

What is Open Protocol at all?

Open Protocol, as the name says, it's a protocol to communicate with Atlas Copco Tightening Controllers or whatever that implement that protocol. Most common Tightening Controllers from Atlas Copco company are PowerFocus4000 and PowerMacs.

Although, some other companies adhered to use the same protocol.

What is OpenProtocolInterpreter?

OpenProtocolInterpreter is a library that converts the ugly string that came from Open Protocol packages, which is commonly called MID, to an object. "Substringing" packages is such a boring thing to do, so let OpenProtocolIntepreter do it for you!

If you're curious, just take a look at their documentation.

How does it work?

It's simple, you give us your string package and we deliver you an object, simple as that!

For example, let's imagine you received the following string package:

string package = "00240005001         0018";

It's MID 5, so OpenProtocolIntepreter will return a MID_0005 class for you with all his datafields and the package entire translated to an object.

Let's see some examples of usage

A simple usage:

MIDIdentifier identifier = new MIDIdentifier();
string midPackage = @"00260004001         001802";
var myMid04 = identifier.IdentifyMid<MID_0004>(midPackage);
//MID 0004 is an error mid which contains which MID Failed and its error code
//Int value of the Failed Mid
int myFailedMid = myMid04.FailedMid; 
//An enum with Error Code
MID_0004.ErrorCode errorCode = myMid04.ErrorCode;

It can generate an object from a string, but can it make it to the other way?? FOR SURE!

MID_0032 jobUploadRequest = new MID_0032();
jobUploadRequest.JobID = 1;

string package = jobUploadRequest.buildPackage();
//Generated package => 00220032001         01

Advanced Section!

Now we will get real! Put one thing in mind, in real world we will always need to build something more complex than the dummies examples we give to you. With this in mind, this section is for you:

How it was built?

Well, FYI it was all built accordingly with Chain Of Responsabilities design pattern, so we iterate among the COMMON and ONLY COMMON MIDs. <dl> <dt>What do I mean by Common mid?</dt> <dd>The docs separate mids by categories, such as "Job MIDs", there will be, Job Info, Ack, Upload Request, etc.</dd> <dd>So we iterate only inside "Job Messages", not in all of available MIDs.</dd> </dl>

MIDs Identifying Customization

We have several MIDs inside Open Protocol documentation, but do you really need all of them? The answer is... NO!

You will probably need only to use a range of MIDs, with this in mind, we did something to make things faster. You can tell us which MIDs we should considerate!

*NOTE: You can register only mids you need to call "processPackage" method

Here is an example:

var myMidIdentifier = new MIDIdentifier(new MID[]
                        {
                            new MID_0001(),
                            new MID_0002(),
                            new MID_0003(),
                            new MID_0004(),
                            new MID_0106()
                        });
//Will work:
MID_0004 myMid04 = myMidIdentifier.IdentifyMid<MID_0004>(package);  
//Won't work:
MID_0030 myMid30 = myMidIdentifier.IdentifyMid<MID_0030>(package);          

In my conception you should always register used MIDs when you are the Integrator

Advanced Example

Declared a delegate:

protected delegate void ReceivedCommandActionDelegate(ReceivedMIDEventArgs e);

ReceivedMIDEventArgs class:

public class ReceivedMIDEventArgs : EventArgs
{
    public MID ReceivedMID { get; set; }
}

Created a method to register all those MID types by delegates:

protected Dictionary<Type, ReceivedCommandActionDelegate> RegisterOnAsyncReceivedMIDs()
{
    var receivedMids = new Dictionary<Type, ReceivedCommandActionDelegate>();
    receivedMids.Add(typeof(MID_0005), new ReceivedCommandActionDelegate(this.onCommandAcceptedReceived));
    receivedMids.Add(typeof(MID_0004), new ReceivedCommandActionDelegate(this.onErrorReceived));
    receivedMids.Add(typeof(MID_0071), new ReceivedCommandActionDelegate(this.onAlarmReceived));
    receivedMids.Add(typeof(MID_0061), new ReceivedCommandActionDelegate(this.onTighteningReceived));
    receivedMids.Add(typeof(MID_0035), new ReceivedCommandActionDelegate(this.onJobInfoReceived));
    return receivedMids;
}

What was done is registering in a dictionary the correspondent delegate for a determinated MID, once done that we just need to invoke the delegate everytime you face a desired MID.

When a package income:

protected void onPackageReceived(string message)
{
    try
    {
        var mid = this.DriverManager.IdentifyMidFromPackage(message);

        //Get Registered delegate for the MID that was identified
        var action = this.onReceivedMID.FirstOrDefault(x => x.Key == mid.GetType());
        
        if (action.Equals(default(KeyValuePair<Type, ReceivedCommandActionDelegate>)))
           return; //Stop if there is no delegate registered for the message that arrived

         action.Value(new ReceivedMIDEventArgs() { ReceivedMID = mid }); //Call delegate
     }
     catch (Exception ex)
     {
        Console.log(ex.Message);
     }
}

This would call the registered delegate which you're sure what mid it is. For example when a MID_0061 (last tightening) pop up, the onTighteningReceived delegate will be called:

protected void onTighteningReceived(ReceivedMIDEventArgs e)
{
    try
    {
        
        MID_0061 tighteningMid = e.ReceivedMID as MID_0061; //Converting to the right mid

        //This method just send the ack from tightening mid
        this.buildAndSendAcknowledge(tighteningMid); 
        Console.log("TIGHTENING ARRIVED")
     }
     catch (Exception ex)
     {
         Console.log(ex.Message);
     }
}

protected void buildAndSendAcknowledge(MID mid)
{
     this.tcpClient.GetStream().Write(new MID_0062().buildPackage()); //Send acknowledge to controller
}

Tips

Instantiate the MIDIdentifier class just once, it takes some time to build all the "chain thing", and you don't want to lose time instantiating it everytime a package arrives.

Controller Implementation Tip: Always TRY to register used MIDs, not all Tightening Controllers use every available MID.

Integrator Implementation Tip: Always DO register used MIDs, I'm pretty sure you won't need all of them to your application.

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on OpenProtocolInterpreter:

Repository Stars
Rickedb/OpenProtocolInterpreter
Converts the ugly ASCII package that came from Open Protocol to an object
Version Downloads Last updated
6.1.0 512 12/11/2023
6.0.0 1,530 5/31/2023
5.1.0 3,281 1/12/2023
5.0.0 1,965 6/6/2022
4.2.0 1,064 2/9/2022
4.1.0 2,527 1/17/2022
4.0.0 464 1/14/2022
3.6.2 1,768 10/15/2021
3.6.1 641 9/23/2021
3.6.0 438 9/9/2021
3.5.0 579 7/19/2021
3.4.3 615 6/1/2021
3.4.2 550 5/31/2021
3.4.1 491 5/7/2021
3.4.0 5,184 4/2/2021
3.3.0 1,312 12/22/2020
3.2.2 495 11/10/2020
3.2.1 3,377 9/15/2020
3.2.0 5,291 6/26/2020
3.1.2 703 3/9/2020
3.1.1 558 2/19/2020
3.1.0 716 2/12/2020
3.0.5 1,394 2/7/2020
3.0.4 506 2/6/2020
3.0.3 1,667 10/23/2019
3.0.2 651 9/18/2019
3.0.1 625 8/19/2019
3.0.0 618 8/14/2019
2.2.1 648 6/21/2019
2.2.0 638 4/8/2019
2.1.2 942 1/11/2019
2.1.1 769 1/10/2019
2.1.0 806 11/8/2018
2.0.1 1,031 6/19/2018
1.0.0 1,186 5/3/2018