GithubHelp home page GithubHelp logo

rickedb / openprotocolinterpreter Goto Github PK

View Code? Open in Web Editor NEW
141.0 20.0 71.0 17.89 MB

Converts the ugly ASCII package that came from Open Protocol to an object

License: MIT License

C# 100.00%
protocol open-protocol atlas copco tightening controller

openprotocolinterpreter's Introduction

Open Protocol Interpreter

OpenProtocol communication utility

  1. What is Open Protocol at all?
  2. What is OpenProtocolInterpreter?
  3. How does it work?
  4. Usage examples
  5. Available on package managers
  6. Advanced section
  7. Tips
  8. Contribute to the project
  9. Still unavailable mids

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 byte[] or 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 Mid0005 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:

var interpreter = new MidInterpreter();
var midPackage = @"00260004001         001802";
var myMid04 = interpreter.Parse<Mid0004>(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
Error errorCode = myMid04.ErrorCode;

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

var jobUploadRequest = new Mid0032(1, 2); //Job id 1, revision 2
var package = jobUploadRequest.Pack();
//Generated package => 00240032002         0001

Get it on NuGet!

Install-Package OpenProtocolInterpreter

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?

It used to rely on Chain Of Responsabilities design pattern, but since we had some problems with instance references, it changed! For now, instead of iterating through all Mids of the same category, it relies on a Dictionary, which every category knows which mid it attends, once it found it creates a new Instance via System.Reflection and parse it.

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 "Parse" method

Here is an example:

string package = "00260004001         001802";
var myCustomInterpreter = new MidInterpreter()
								.UseAllMessages(new Type[]
		                        {
		                            typeof(Mid0001),
		                            typeof(Mid0002),
		                            typeof(Mid0003),
		                            typeof(Mid0004),
		                            typeof(Mid0106)
		                        });
//Will work:
var myMid04 = myCustomInterpreter.Parse<Mid0004>(package);
//Won't work, will throw NotImplementedException:
var myMid30 = myCustomInterpreter.Parse<Mid0030>(package);        
//Won't work, will throw InvalidCastException:
var myMid01 = myCustomInterpreter.Parse<Mid0001>(package);

When you don't know which package will come, use Parse overload, not Parse<DesiredMid>. If you want, take a look at the sample on this repository.

If necessary, there is a new overload where you can define if you're the controller or the integrator, which will automatically handle implemented mids

MIDs Overriding

Maybe you have a totally crazy controller that does not implement the Mid as the documentation says or you might want to inject your own Mid inheriting another Mid, so you can customize it and add more properties to handle some conversions. Anyway, if you need that, it's possible to override!

Here is an example:

//This will override Mid 81 with my custom Mid
var _midInterpreter new MidInterpreter().UseAllMessages()
                                        .UseTimeMessages(new Dictionary<int, Type>() { { 81, typeof(OverridedMid0081) } });


public class OverridedMid0081 : Mid0081
{
    public string FormattedDate
    {
        get => Time.ToString("dd/MM/yyyy HH:mm:ss");
        set => Time = DateTime.Parse(value);
    }

    public OverridedMid0081()
    {
        
    }

    public override string Pack()
    {
        Time = TestCustomMid.Now;
        return base.Pack();
    }
}

Adding MIDs that are not in documentation

Maybe your controller is weird and have unknown MID numbers, MIDs that are not in the documentation and you want to inject into MidInterpreter, there is a way:

var _midInterpreter new MidInterpreter().UseAllMessages()
                                        .UseCustomMessage(new Dictionary<int, Type>() { { 83, typeof(NewMid0083) } });

public class NewMid0083 : Mid
{
    private readonly IValueConverter<DateTime> _dateConverter;
    private const int LAST_REVISION = 1;
    public const int MID = 83;

    public DateTime Time
    {
        get => GetField(1, (int)DataFields.TIME).GetValue(_dateConverter.Convert);
        set => GetField(1, (int)DataFields.TIME).SetValue(_dateConverter.Convert, value);
    }
    public string TimeZone
    {
        get => GetField(1, (int)DataFields.TIMEZONE).Value;
        set => GetField(1, (int)DataFields.TIMEZONE).SetValue(value);
    }

    public NewMid0083() : base(MID, LAST_REVISION)
    {
        _dateConverter = new DateConverter();
    }

    protected override Dictionary<int, List<DataField>> RegisterDatafields()
    {
        return new Dictionary<int, List<DataField>>()
        {
            {
                1, new List<DataField>()
                        {
                            new DataField((int)DataFields.TIME, 20, 19),
                            new DataField((int)DataFields.TIMEZONE, 41, 2)
                        }
            }
        };
    }

    public enum DataFields
    {
        TIME,
        TIMEZONE
    }
}

NOTE: Custom messages might not perform as fast as other MIDs because they don't have optimizations for finding it

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(Mid0005), new ReceivedCommandActionDelegate(OnCommandAcceptedReceived));
    receivedMids.Add(typeof(Mid0004), new ReceivedCommandActionDelegate(OnErrorReceived));
    receivedMids.Add(typeof(Mid0071), new ReceivedCommandActionDelegate(OnAlarmReceived));
    receivedMids.Add(typeof(Mid0061), new ReceivedCommandActionDelegate(OnTighteningReceived));
    receivedMids.Add(typeof(Mid0035), new ReceivedCommandActionDelegate(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
    {
        //Parse to mid class
        var mid = Interpreter.Parse(message);

        //Get Registered delegate for the MID that was identified
        var action = 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
    {
        Mid0061 tighteningMid = e.ReceivedMID as Mid0061; //Casting to the right mid

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

protected void BuildAndSendAcknowledge(Mid mid)
{
     TcpClient.GetStream().Write(new Mid0062().Pack()); //Send acknowledge to controller
}

Tips

Instantiate the MIDIdentifier class just once and keep working with it!

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.

Contribute to the project

Lot's of effort were given to this project and by seen people using it motivated me a lot to improve it more and more.

Does it help you a lot? That's awesome and very rewarding! But if you wish, you can support and help to motivate the constant improving of this library by contributing in OpenCollective.

List of still unavailable Mids

  • Mid 0700;
  • Mid 0900;
  • Mid 0901;
  • Mid 1000;
  • Mid 1001;
  • Mid 1601;
  • Mid 1602;
  • Mid 1900;
  • Mid 1901;
  • Mid 2100;
  • Mid 2500;
  • Mid 2501;
  • Mid 2600;
  • Mid 2601;
  • Mid 2602;
  • Mid 2603;
  • Mid 2604;
  • Mid 2605;
  • Mid 2606.

Feel free to fork and contribute to add any of those mids.

openprotocolinterpreter's People

Contributors

artleo-prodrive avatar coderpatros avatar exist16 avatar gus-v avatar meldinoor avatar rickedb avatar wadjet-informatics avatar xgusu 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  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

openprotocolinterpreter's Issues

Mid0033.Pack() throws an exception, if revision > 1

If I try to use revision 2 (or 3 or 4), Mid0033.Pack() throws an exception:

System.Collections.Generic.KeyNotFoundException: The given key '2' was not present in the dictionary.
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at OpenProtocolInterpreter.Mid.BuildHeader() in ...\src\OpenProtocolInterpreter\MID.cs:line 45
   at OpenProtocolInterpreter.Mid.Pack() in ...\src\OpenProtocolInterpreter\MID.cs:line 56
   at OpenProtocolInterpreter.Job.Mid0033.Pack() in ...\src\OpenProtocolInterpreter\Job\Mid0033.cs:line 148

The reason seems to be: RegisterDatafields() only has definitions for revision 1.

By the way, I do not understand this part of the open protocol documentation: in revision 2, the Job list starts at index 92-93, but with revision 3 (and 4), it is documented to start at 94-95. Why and how should this work?

Mid0076 Rev.2

I added the Revision 2 for the alarm Mid0076.

It's in the specification of the release 2.8.0 that I found here:
https://github.com/netsmarttech/node-open-protocol/blob/master/docs/OpenProtocolSpecification_R280.pdf

private const int LAST_REVISION = 2;

protected override Dictionary<int, List<DataField>> RegisterDatafields()
{
    return new Dictionary<int, List<DataField>>()
    {
        {
            1, new List<DataField>()
                    {
                        new DataField((int)DataFields.ALARM_STATUS, 20, 1),
                        new DataField((int)DataFields.ERROR_CODE, 23, 4, ' ', DataField.PaddingOrientations.LEFT_PADDED),
                        new DataField((int)DataFields.CONTROLLER_READY_STATUS, 29, 1),
                        new DataField((int)DataFields.TOOL_READY_STATUS, 32, 1),
                        new DataField((int)DataFields.TIME, 35, 19)
                    }
        },
        {
            2, new List<DataField>()
                    {
                        new DataField((int)DataFields.ALARM_STATUS, 20, 1),
                        new DataField((int)DataFields.ERROR_CODE, 23, 4, ' ', DataField.PaddingOrientations.LEFT_PADDED),
                        new DataField((int)DataFields.CONTROLLER_READY_STATUS, 30, 1),
                        new DataField((int)DataFields.TOOL_READY_STATUS, 33, 1),
                        new DataField((int)DataFields.TIME, 36, 19)
                    }
        },

    };
}

Conexรฃo C# com power mac

Boa tarde, serรก que vocรช poderia me dar um auxilio?
Como faรงo para dar um keepAlive?
baixei a biblioteca, mas mesmo assim ela nรฃo reconhece!

Obrigado desde de jรก.

can this open protocol interpreter used on RAD controller?

hi everyone:
this is not an issue and we just didn't find a right place to post this question so we can only write it down here.

We are using RAD controller E-RAD BLU 8000-m. did anyone applied this open protocol interpreter to this model? We already consulted RAD and they have confirmed this model supports open protocol but so far we didn't have any luck to use this interpreter to get information from controller.

any suggestion is highly appreciated.

Support for Mid 9998

Is it possible to add support for the MID 9998 (ApplicationLinkError)?

The message is sent by the controller if there was an protocoll error.

Mid0011 does not work because of incorrect length calculation

in Parse() you set the size:

GetField(1, (int)DataFields.EACH_PARAMETER_SET).Size = package.Length - GetField(1, (int)DataFields.EACH_PARAMETER_SET).Index;

This is wrong, because "package" includes the Message End termination NUL.
If you add a "- 1", Mid0011 works fine.

My fix is a bit more secure:

int length = package.Length - GetField(1, (int)DataFields.EACH_PARAMETER_SET).Index;
if (package.Length > 0 && package[package.Length - 1] == '\0')
{
  length--;
}
GetField(1, (int)DataFields.EACH_PARAMETER_SET).Size = length;

May be bug or Some other problem

I was communicating to one Open protocol controller with 3 tool. So first we try to use MID0100 but for that we are getting parsing error while receiving the response from the controller. So vendor of controller suggest that we can use 3 different port for 3 tool of the controller so we changed accordingly. We are testing everthing with the sample app in the repo. So we connected successfully but we are getting the response from all the 3 tool multple times. Even controller is sending one time but we are receiving multiple times. This is the first problem we faced but after some time we are having another big problem , controller is sending the data of all the 3 tool but we are receiving only for either 1 or 2 tool. When we restart the app then we again receive the data from all the 3 tool for 2-3 times but again then we received the data only for 1 or 2 tool. Here I am attaching code and log file as well.
Log_20201001.log

Code.txt

Mid0076 (Alarm status) always creates revision 3

If a Mid0076 is created using a revision 1/2/3 constructor, it always is revision 3, because there are no revision arguments in the constructors. Therefore always LAST_REVISION, which is 3, is used.

By the way, revision 3 cannot be used, because Mid0070 (Alarm subscribe) only supports revision 2.

possible crash in class Mid.ProcessDataFields

Your code looks like this:

protected virtual void ProcessDataFields(string package)
{
    if (!RevisionsByFields.Any())
       return;

   int revision = HeaderData.Revision > 0 ? HeaderData.Revision : 1;
   for (int i = 1; i <= revision; i++)
       ProcessDataFields(RevisionsByFields[i], package);
}

The loop must do a check to avoid a crash, if a revision is not included in RegisterDatafields().

for (int i = 1; i <= revision; i++)
{
    if (RevisionsByFields.ContainsKey(i) == true)    
    {
        ProcessDataFields(RevisionsByFields[i], package);
    }
}

StrategyOptionsConverter creates 10 instead of 5 bytes

OpenProtocolInterpreter.Converters, class StrategyOptionsConverter, ConvertToBytes():

This method creates an output of 10 bytes. But correct is 5 bytes. Maybe a block copy bug from TighteningErrorStatusConverter.cs, which uses 10 bytes. This problem makes Mid0061 unusable. :(

// byte[] bytes = new byte[10];        // wrong
byte[] bytes = new byte[5];            //correct

// bytes[2] = bytes[3] = bytes[4] = bytes[5] = bytes[6] = bytes[7] = bytes[8] = bytes[9] = 0;   // wrong
bytes[2] = bytes[3] = bytes[4] = 0;                                                             //correct

Issue MID 0245

I'm using your excellent library to realize an Open Protocol Simulator. During my development i noticed an issue into MID 0245. I suppose the issue derive from a wrong cut and paste.
In my opinion the code should be fixed into this point

    public class Mid0245 : Mid, IPLCUserData, IIntegrator
    {
        private readonly IValueConverter<int> _intConverter;
        private const int LAST_REVISION = 1;
        public const int MID = 245;

        public int Offset
        {
            //old:get => GetField(1, (int)DataFields.USER_DATA).GetValue(_intConverter.Convert);
            //old:set => GetField(1, (int)DataFields.USER_DATA).SetValue(_intConverter.Convert, value);
			get => GetField(1, (int)DataFields.OFFSET).GetValue(_intConverter.Convert);
			set => GetField(1, (int)DataFields.OFFSET).SetValue(_intConverter.Convert, value);
        }

I'm not sure the USER_DATA field must be filled to 200 chars.
The documentation say:

Offset 21-23 Three ASCII digits Range 000-099Specify the address offset in number of bytes for theuser data in the PLC.The data is written to address 13000 + Offset in thePLC
User data 24-max 223 Minimum 2 and maximum 200 ASCII characters.See MID 0240 for a description.The maximum length for the field is 200 โ€“ 2 * Offset

Can you confirm the need of that padding?

Have a nice day

Roberto Guerzoni

(Mid0061) Tighten Error Status not parsing properly

Hello,

With the following message:
03850061002 0000010000020003SU_ST7.1_ETV100 04 05000006001070208000670900001000001101221301401501611711811912000000000022100340022004600230040002400069525000252600600270000028000002900360300300031000503200033150340003500000036999900370000003800000039000000400000004100002341084200000430000044 C0720021452020-06-01:15:48:27462020-05-12:07:34:57

Should return Rundown angle min shut off, nevertheless, allways return null.

Tightening Subscribe Response MID0061

The MID0061 object through MIDIncome will not update to new data. When I run more than one tightening the tightening information received in the onTighteningReceived function is always the same as the first tightening received. I have looked at the raw data coming in the logs and I can see they are different and the Tightening ID is increasing in the raw data string but the new data is not being parsed into the object.

I am using Mid0060 revision 6 because my controller reports that revision 7 is not available.

Mid0033.Pack() creates invalid message, if parameterSetList is empty

If the provided parameterSetList is empty (0 entries), the string created by Pack() ends with 120013;. This leads to an error on the Integrator side. Correct would be 120013. The semicolon may not appear, if the number of parameter sets is 0.
The revision has been set to 1. I did not test PackBytes().

Sample Code: SendAndWaitForResponse() -- waiting for 500 ms causes messages to be sent twice

public Mid SendAndWaitForResponse(string message, TimeSpan timeout)
        {
            try
            {
                System.Threading.Thread.Sleep(500); // HERE
                Mid midResponse = null;

                Console.WriteLine($"Sending message: {message}");
                Message response = this.simpleTcpClient.WriteLineAndGetReply(message, timeout);

                Console.WriteLine((response != null) ? $"Response: {response.MessageString}" : "TIMEOUT!");

                if (response != null)
                {
                    KeepConnectionAlive();
                    midResponse = _midInterpreter.Parse(response.MessageString);
                }

                return midResponse;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Exception: {ex.Message}");
                return null;
            }
        }

When running the sample app, sleeping for 500 ms will cause the heartbeat/MID 9999 to be received twice.

Possibly because the Timer thread and Receive thread are competing?

Or maybe these functions aren't meant to be ran sequentially with a significant delay to receive a response.

Bugs processing MID0106

With the newer versions the MID0106 is not working properly, here an example (replace _ with space):
03370106____________01030201030000723323040105SU_ST2.1_PwMACS_____062021-05-06:13:46:14075008Mode_50_____________09110011________________________________________1202130114115_16117_______18-2885.719_______20_______21_______22_______130214115_16117_______18-2885.819_______20_______21_______22_______2301Data_No_Station_____I_100000002438

This is an example of a loosen, the BoltsData, in the angle, should return -2558.7
But depending on the version returns:
V: 3.4.0 => angle 0
V: 3.3.0 => angle 0
V: 3.2.2 => angle -28857 (no decimal, probably due to CultureInfo)

Mid0031 Parse() always throws Exception

Mid0031 cannot be parsed at all.
The loop in Converters.JobIdListConverter.Convert(string value) looks like this:

  for (int i = 0; i < value.Length; i+= _jobSize)

correct would be:

  for (int i = 0; i < value.Length - 1; i+= _jobSize)

For example, if revision=1 and there are three Ids, value is "010205\0". value.Length is 7 because of the NUL at its end.
Therefore the loop executes too far (including i=6) and the following value.Substring(i, _jobSize) throws the exception.

Mid0061 - TighteningErrorStatus not working properly

OpenProtocolInterpreter Version: 3.2.2

For the following string (replace _ with space):

03850061002_____0000010000020003RA_ST5.3_ETV150__________04_________________________05000006002070208000670900001000001101221301401501611711811912000000081942101030022012700230115002400312025000202600200270000028000002900360300850031000023200033150340003500030036999900370000003800030039002000400000004100001495124200000430000044______C0690301452020-11-09:17:35:59462020-07-24:11:35:42`

When decoded sending the telegram as string, detects properly TriggerLost and RundownAngleMinShutOff.
But if you send it as byte[]

MidInterpreter _midInterpreter = new MidInterpreter().UseAllMessages();
// Trigger lost , Rundown angle min shut off
string telegram = "03850061002 0000010000020003RA_ST5.3_ETV150 04 05000006002070208000670900001000001101221301401501611711811912000000081942101030022012700230115002400312025000202600200270000028000002900360300850031000023200033150340003500030036999900370000003800030039002000400000004100001495124200000430000044 C0690301452020-11-09:17:35:59462020-07-24:11:35:42";
var mid = _midInterpreter.Parse(Encoding.ASCII.GetBytes(telegram));
var m = mid as Mid0061;

The TighteningErrorStatus that detects is:

=>AngleMaxMonitor: true
AngleMaxShutOff: false
CurrentLimitReached: false
CurrentMonitoringMaxShutOff: false
DisableDrive: false
DsMeasureFailed: false
=>DynamicCurrentMonitoringMax: true
DynamicCurrentMonitoringMin: false
=>EndTimeOutShutOff: true
MultistageAbort: false
=>PostViewTorqueAngleTooSmall: true
PostViewTorqueMaxTorqueShutOff: false
PostViewTorqueMinTorqueShutOff: false
PrevailTorqueCompensateOverflow: false
PrevailTorqueMaxShutOff: false
PrevailTorqueMinShutOff: false
Rehit: false
=>RemoveFastenerLimitExceeded: true
RundownAngleMaxShutOff: false
RundownAngleMinShutOff: false
=>SelftapTorqueMaxShutOff: true
=>SelftapTorqueMinShutOff: true
SyncTimeout: false
ToolHot: false
TorqueLessThanTarget: false
TorqueMaxShutOff: false
TransducerCorrupt: false
TransducerLost: false
TransducerShorted: false
=>TriggerLost: true
YieldNutOff: false
YieldTooFewSamples: false

Request for Mid0701 (Tool list upload reply)

I would like to see Mid0701 (Tool list upload reply) supported by your package.
It is used to upload the Tool list according to Mids 10-13 for Psets.
Okay, it's part of OpenProtocol v2, but it would be very helpful for me (and others).
I tried to implement it as custom Mid by my own, but because of the repeating items it is somewhat complicated for a girl not familiar with you package internals.
For you, it should be easy, bacause you already implemented similar lists in the Mids 106/107.

Communication crash when send unexpected mid

After you subscribe to Mid0060, and you receive a a Mid61(tightening result ).
and Keep alive is send before the ACK Mid62 and crash the communication.
Any tips ? how to solve this ?

error

Mid0061 TighteningErrorStatus.Get doesn't return what has been Set

I run into a problem, initializing TighteningErrorStatus in Mid0061:

this code doesn't work:

mid0061.TighteningErrorStatus = new TighteningErrorStatus();
mid0061.TighteningErrorStatus.Rehit = true;

this works:

TighteningErrorStatus tes = new TighteningErrorStatus();
tes.Rehit = true;
mid0061.TighteningErrorStatus = tes;

The property TighteningErrorStatus doesn't return on Get() what has been set with Set().
I do not know yet, if this is a local problem with TighteningErrorStatus or if other properties (in other Mids) are affected as well.

Mid0061 TighteningErrorStatus2Converter.ConvertToBytes() causes NullReferenceException

OpenProtocolInterpreter.Converters.TighteningErrorStatus2Converter.ConvertToBytes() crashes if Reserved is not set.
If I use Rev. 6 in Mid0061, I must initialize Reserved, to avoid a crash later in ConvertToBytes():

mid0061.TighteningErrorStatus2 = new TighteningErrorStatus2
{
    Reserved = new byte[10]
};

This should not be necessary and should be done in the constructor or checked in ConvertToBytes().

Multi-spindle sample

I made some very simple multi-spindle sample based on SimpleTcp library. Main windows uses WPF instead of windows forms.
Sample contains only basic communication and MID 0100 subscription. Some error handling and code brushing is necessary but based on my test it looks like it works :)
Btw, zip contains modified OpenProtocolInterpreter library because original contains some multispindle related bugs. Also, this modifications contains basic (and not finished) mode support and MID 0701

OpenProtocolInterpreter.Sample2.zip

LEFT_PADDED missing in Mid0002

A while ago, you added LEFT_PADDED to CELL_ID and CHANNEL_ID - fine, these were missing in earlier versions.
But SYSTEM_TYPE and SYSTEM_SUBTYPE do need LEFT_PADDED as well - please add these!

Add string packages support for Mid0065

Mid0065 string methods is marked as Obsolete and not supported for revisions above rev 1, however we can do it like it's done for Mid0061 by transforming byte[] fields from ASCII int to byte array and vice versa.

See also #24

Bug Collecting Tightening Error Status Mid0061 Rev.2

I've found the following error. In Mid0061 Rev.2, I got the following code:
03850061002 0000010000020003SU_ST7.1_ETV100 04 05000006001070208000670900001000001101221301401501611711811912000000000022100340022004600230040002400177225000252600600270000028000012900360300300031000123200033150340003500000036999900370000003800000039000000400000004100002321914200000430000044 C0720021452020-05-29:09:55:05462020-05-12:07:34:57

The tightening error status is not beign recognised, I think it's because it returns 0000000002 instead of 0000000010

I've also tested with Rev.6:
05260061006 0000010000020003SU_ST7.1_ETV100 04 05000006001070208000670900001000001111221311411511611711811912000000000002100340022004600230040002400400125000252600600270000028003532900360300300031021933200033150340003500000036999900370000003800000039000000400000004100002322494200000430000044 C0720021452020-05-29:10:47:33462020-05-12:07:34:5747 SU_Tubo pinza_40 Nm481490150 51 52 53 54000000550000000000

image

The type or namespace name 'MID_0005' could not be found

while trying to build OpenProtocolInterpreter.Sample I get the Error: The type or namespace name 'MID_0005' could not be found (are you missing a using directive or an assembly reference?) OpenProtocolInterpreter.Sample

any idea to resolve it?

DecimalConvert still not working for ES computer

I've been testing for a while, and I've found a solution for the issue.
The .Replace(',', '.') didn't fix it properly.
The following code works fine in my computer (I assume should work properly in all computers due to the CultureInfo).

    public override decimal Convert(string value)
    {
        decimal decimalValue = 0;
        if (value != null)
            decimal.TryParse(value.Replace(',', '.'), NumberStyles.AllowDecimalPoint, new CultureInfo("en-US"), out decimalValue);

        return decimalValue;
    }

I'm not sure if it's necessary change it in other places (I haven't found a DoubleConvert, FloatConverter or other type of decimal)

DecimalConverter bug

Due to some reason, when you convert BoltData from MID0106 sometimes the data is not well converted (for example when the tool loosens and returns a negative angle).

public override decimal Convert(string value)
{
    decimal decimalValue = 0;
    if (value != null)
        decimal.TryParse(value.ToString(), out decimalValue);

    return decimalValue;
}

I fixed it adding the following replace.

public override decimal Convert(string value)
{
    decimal decimalValue = 0;
    if (value != null)
        decimal.TryParse(value.ToString().Replace('.', ','), out decimalValue);

    return decimalValue;
}

Perhaps can be also fixed using CultureInfo, the language of my client is es-ES.

TotalParameterSets in Mid0011 is always 0

While trying to fix Issue #59 I found the property TotalParameterSets to be always 0.
If I received a Mid0011, ParameterSets is fine and of course ParameterSets.Length holds the number of entries.
But TotalParameterSets is 0 and therefore cannot be used.
I tried to fix Issue #59 by setting the Size to TotalParameterSets * 3, but as it is always 0, it didn't work.

NullReference exception when try to set StrategyOptions on MID0061

In my project I need to get MID0061 message and save it into the database. To test it I created and MID0061 object , created a StrategyOptions parameter and set it to Strategy option field of MID0061.
I got a NullReferenceException on SetRawValue which takes byte[] parameter type as value on the line of Size = Value.Length. Because only RawValue is set in this method, Value is everytime null in this case.

 public virtual void SetRawValue<T>(Func<char, int, PaddingOrientations, T, byte[]> converter, T value)
        {
            CachedValue = null;
            RawValue = converter(_paddingChar, Size, _paddingOrientation, value);
            Size = Value.Length;
        }

I want to fix it but it is being used by more than 100 places. Could anyone help me with this issue?

Thanks

Is it supported on Linux ?

Is this library supported on linux platform ? If yes, can you guide me through the set up and running a sample program in linux environment ?

Mid0013 ignores constructor parameter: parameterSetName

If I provide the parameterSetName to the constructor of Mid0013, it will be ignored. The reason for this is in the revision 1 constructor where you wrote:

ParameterSetName = ParameterSetName;
                 //^ capital P is wrong

correct is:

ParameterSetName = parameterSetName;

Mid0035 has LAST_REVISION=4 although there is revision 5 support

In Mid0035 LAST_REVISION is set to 4, although there is a partly implemented revision 5 support.
Properties have revision 5 support, but a revision 5 constructor is missing.
Should be easy to finalize the revision 5 support.
Not urgent, I don't think, I'll need this soon.

ProcessHeader(string package) - Default revision

Some messages from some controllers doesn't contains revision, for example MID 0015:
00420015____________0022017-10-03:14:12:30
In this case message parsing fails because MID revision parsed as 0 and DataField doesn't contains data for revision 0.
Possible fix is to change default revision to 1 (Mid.cs:100)
Revision = (package.Length >= 11 && !string.IsNullOrWhiteSpace(package.Substring(8, 3))) ? Convert.ToInt32(package.Substring(8, 3)) : 1,

Mid0106 error

The following piece of code in PowerMACS/Mid0106 is wrong.

public bool SimpleStatus
{
    get => GetField(1, (int)DataFields.MODE_NUMBER).GetValue(_boolConverter.Convert);
    set => GetField(1, (int)DataFields.MODE_NUMBER).SetValue(_boolConverter.Convert, value);
}

Should be:

public bool SimpleStatus
{
    get => GetField(1, (int)DataFields.SIMPLE_STATUS).GetValue(_boolConverter.Convert);
    set => GetField(1, (int)DataFields.SIMPLE_STATUS).SetValue(_boolConverter.Convert, value);
}

Loop may crash in class ParameterSetIdListConverter

OpenProtocolInterpreter.Converters, class ParameterSetIdListConverter, public override IEnumerable<int> Convert(string value):

for (int i = 0; i < value.Length; i += 3)
must be changed into
for (int i = 0; i < value.Length - 2; i += 3)

Otherwise the method crashes if value has the max. length (9977 characters or so).

Mid0015 ParameterSetId Get/Set Uses revision 1's structure for revision 2 data.

This causes incorrect parsing when receiving revision 2 strings.

proposed fix:

        public int ParameterSetId
        {
            get => GetField(HeaderData.Revision, (int)DataFields.PARAMETER_SET_ID).GetValue(_intConverter.Convert);
            set => GetField(HeaderData.Revision, (int)DataFields.PARAMETER_SET_ID).SetValue(_intConverter.Convert, value);
        }

Subscribing to MID 0900 using MID 0008

As stated in the OpenProtocol PDF:

5.27.1.2 Subscribe, MID 0900 Trace data message
Used by the integrator to subscribe on trace data. MID is used together with MID 0008, see Table 23 MID 0008, revision 1, this begins at byte 30 after the message header.
Message sent by: Integrator
Answer: MID 0005 Command accepted with MID 900 in the data field or MID 0004 Command error with MID 900 in the data field and error code, Subscription MID Revision unsupported or Subscription already exist or Subscription on specific data not supported or Invalid data

I am trying to implement Mid0900 and by using Mid0008 to subscribe to Trace Curve Data messages sent by the controller. However I always get a Mid0004 with error code 99 (Unknown Mid) as a response from the PF4000 controller. I am hoping someone may see the error in my logic or this might be a bug.

           // Create the Mid0008 message to be sent to the controller
            var mid0008 = new Mid0008()
            {
               SubscriptionMid = "0900",
               WantedRevision = 001,
               ExtraDataLength = 35,
               ExtraData = "10000000000000000000000000000101002",
            };

            pack = protocolFunctions.SendAndWaitForResponse(mid.Pack(), TimeSpan.FromSeconds(10));
            if (pack != null)
            {
               if (pack.HeaderData.Mid == Mid0004.MID)
               {
                  var mid04 = pack as Mid0004;
                  Console.WriteLine($@"Error (MID 0004):
                                         Error Code: <{mid04.ErrorCode}>
                                         Failed MID: <{mid04.FailedMid}>");
               }
               else
                  Console.WriteLine($"Curve subscription accepted!\n");
            }
            protocolFunctions.AddUpdateOnReceivedCommand(typeof(Mid0900), OnCurveReceived);

I believe my extra data logic is correct according to Table 195 Extra data field in the OpenProtocol PDF

Send Alternatives 1 UI Following alternatives are available. One ASCII digit 0=Only new data, 1= Stored data from given index, 2 Stored data from given time stamp, 3 Stored data between two indexes, 4 Stored data between two given time stamps in Unix time ( Seconds since 1970-01-01).. If = 0 then only the new data generated after the subscription is done is sent to the subscriber. Old unsent data will not be sent to the subscriber. If = 1 the data from given INDEX is sent inclusive the latest stored. If = 2 the data from given time stamp in Unix format is sent inclusive the latest stored. If = 3 the data between two given indexes is sent If = 4 the data between two given time stamps in Unix time is sent
Data Identifier Time Stamp type 19 T The identifier is a Time stamp of the requested data. The first data sent will be the first data and inclusive this time stamp and forward up to and inclusive the last one. If the data is not found, rewind will be to oldest possible data. All data from this point up to the newest available will be sent directly on subscribe. If not used filled in with zeroes e.g at alternative 1. At alternative 2 it contains the Time Stamp ex. 2015.10.01:19:01:30.
Data identifier Index type or unix time type 10 UI The Identifier INDEX or the UNIX time (at Alternative 2) of the data to rewind to. 10 bytes. Only used for old stored process data. The first data sent will be the data from and inclusive this point and forward up to and inclusive the last one. If the data is not found, or if the value is 0, rewind will be to oldest possible data. All data from this point up to the newest available will be sent directly on su
Number of trace types 2 UI The number of trace types subscribed for
Trace Type 3 UI Type of the trace curve subscribed for. This field is repeated the Number of trace types. 1 = Angle trace 2 = Torque trace 3 = Current trace 4 = Gradient trace 5 = Stroke trace 6 = Force trace

I also added a new MID category called TighteningResults:

namespace OpenProtocolInterpreter.TighteningResults
{
   internal class TighteningResultMessages : MessagesTemplate
   {
      public TighteningResultMessages() : base()
      {
         _templates = new Dictionary<int, MidCompiledInstance>()
            {
                { Mid0900.MID, new MidCompiledInstance(typeof(Mid0900)) },
               // { Mid0901.MID, new MidCompiledInstance(typeof(Mid0901)) },
            };
      }

      public TighteningResultMessages(IEnumerable<Type> selectedMids) : this()
      {
         FilterSelectedMids(selectedMids);
      }

      public TighteningResultMessages(InterpreterMode mode) : this()
      {
         FilterSelectedMids(mode);
      }

      public override bool IsAssignableTo(int mid) => mid > 900 && mid < 902;
   }
}

Which is then added MessageInterpreterExtensions.cs:

public static MidInterpreter UseAllMessages(this MidInterpreter midInterpreter, InterpreterMode mode = InterpreterMode.Both)
        {
            return midInterpreter
                .UseAlarmMessages(mode)
                .UseApplicationControllerMessage(mode)
                .UseApplicationSelectorMessages(mode)
                .UseApplicationToolLocationSystemMessages(mode)
                .UseAutomaticManualModeMessages(mode)
                .UseCommunicationMessages(mode)
                .UseIOInterfaceMessages(mode)
                .UseJobMessages(mode)
                .UseAdvancedJobMessages(mode)
                .UseMotorTuningMessages(mode)
                .UseMultipleIdentifiersMessages(mode)
                .UseMultiSpindleMessages(mode)
                .UseOpenProtocolCommandsDisabledMessages(mode)
                .UseParameterSetMessages(mode)
                .UsePLCUserDataMessages(mode)
                .UsePowerMACSMessages(mode)
                .UseResultMessages(mode)
                .UseStatisticMessages(mode)
                .UseTighteningMessages(mode)
                .UseTighteningResultsMessages(mode) // added here
                .UseTimeMessages(mode)
                .UseToolMessages(mode)
                .UseUserInterfaceMessages(mode)
                .UseVinMessages(mode);
        }

Am I missing something in regards to subscripting to Mid0900 using Mid0008? Does the PF4000 use MID0900?

Insight on this would be greatly appreciated

Mid0061 TighteningErrorStatus - wrong bit field encoding?

If I set the Rehit flag in the TighteningErrorStatus entry of Mid0061, I get an encoded value of 4194304.
Rehit is documented to be bit 18. Because they seem to count from 1, it should be 2^17 = 131072. But it isn't. Why?

And the bits in StrategyOptions count from 0 in the documentation, but you start with 1. Hmmm...
As long as encoding and decoding both is done by your OpenProtocolInterpreter, this may work. But what happens, if another code counts and converts in a different way. The bits all would be messed up and nothing would work.

sample project job info subscribe output update problem.

the codes below works only for the first arrived data. it shows only the data of the first package. code ignores consecutive Mid0035 packets although message arrived updated on the output screen.
Which part do I have to modify?

Console.WriteLine($@"JOB INFO RECEIVED (MID 0035):
Job ID: <{jobInfo.JobId}>
Job Status: <{(int)jobInfo.JobStatus}> ({jobInfo.JobStatus.ToString()})
Job Batch Mode: <{(int)jobInfo.JobBatchMode}> ({jobInfo.JobBatchMode.ToString()})
Job Batch Size: <{jobInfo.JobBatchSize}>
Job Batch Counter: <{jobInfo.JobBatchCounter}>
TimeStamp: <{jobInfo.TimeStamp.ToString("yyyy-MM-dd:HH:mm:ss")}>
");

Message arrived: 00830035004 0000 010001020030040004050002062019-11-17:15:28:05070010800209011001
Sending message: 00200036004
JOB INFO RECEIVED (MID 0035):
Job ID: <1>
Job Status: <0> (NOT_COMPLETED)
Job Batch Mode: <0> (ONLY_OK_TIGHTENINGS)
Job Batch Size: <4>
Job Batch Counter: <2>
TimeStamp: <2019-11-17:15:28:05>
Message arrived: 00830035004 0000 010001020030040004050003062019-11-17:15:28:10070010800209011001
Sending message: 00200036004
JOB INFO RECEIVED (MID 0035):
Job ID: <1>
Job Status: <0> (NOT_COMPLETED)
Job Batch Mode: <0> (ONLY_OK_TIGHTENINGS)
Job Batch Size: <4>
Job Batch Counter: <2>
TimeStamp: <2019-11-17:15:28:05>

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.