S7NetPlus / s7netplus

S7.NET+ -- A .NET library to connect to Siemens Step7 devices
MIT License
1.29k stars 577 forks source link

Can s7netplus read cpu status? #489

Closed Himmelt closed 1 year ago

Himmelt commented 1 year ago

Can s7netplus read cpu status?

I want to display target cpu is runing or stopping in app ui.

mycroes commented 1 year ago

At the moment it can't. If I'm not mistaken I have seen this implemented in an open source library, I'll try to find it and then I should be able to add it to S7NetPlus as well...

mycroes commented 1 year ago

I've spent a couple of hours searching, but couldn't find any implementation yet. However, I did find a Wireshark dump that contains PLC status, the Wireshark S7 dissector actually knows the meaning of all the values, so I'll try to use that as base.

I won't be able to test this on short notice myself, but I'll try to add the functionality, maybe you can test it for me?

Himmelt commented 1 year ago

Sure, I can test this it with a real PLC. If you finished, @ me, I will test it.

And more, I found something from snap7/sharp7/plc4x, maybe helpful? apache plc4x Snap7 Sharp7

int TSnap7MicroClient::opGetPlcStatus()
{
    int *Status;
    int Result;

    Status =(int*)Job.pData;
    Job.ID     =0x0424;
    Job.Index  =0x0000;
    Job.IParam =0;
    Result     =opReadSZL();
    if (Result==0)
    {
        switch (opData[7])
        {
            case S7CpuStatusUnknown :
            case S7CpuStatusRun     :
            case S7CpuStatusStop    : *Status=opData[7];
            break;
            default :
            // Since RUN status is always $08 for all CPUs and CPs, STOP status
            // sometime can be coded as $03 (especially for old cpu...)
                *Status=S7CpuStatusStop;
        }
    }
    else
        *Status=0;
    return Result;
}
mycroes commented 1 year ago

I had actually looked at Snap7 and missed this one. It's certainly useful, because I was going to use SZL 0x0074 which actually is Status of all LEDs (according to the Wireshark dissector), but I guess testing 0x0424 for status 8 might be a more proven way of doing this, especially since the comments hint at support for all CPUs and CPs with that approach.

I expect I have this working somewhere next week, no promises on exact date because I'm actually on holiday till tuesday. Half of it seems to be in place now though, I expect the request to be fine so it's a matter of handling the response mostly.

mycroes commented 1 year ago

Hi @Himmelt, sorry for the delay on this. PR #491 might actually work, I'm not 100% sure if I used the correct offset though. I intend to add a unit test to verify, but just haven't gotten to doing that yet. In the meantime, you can download the NuGet package that's created by the _createnuget action. Keep in mind that I implemented it as returning the status as a byte. If the value is 8, then the PLC should be in run. I have a few busy days coming up, so I'm not sure when exactly I'll be able to finish the unit test, but perhaps you can test this with an actual PLC and we'll know whether it's working before I get to it.

Himmelt commented 1 year ago

Hi @mycroes , I have tested it with 1500 on PLCSIM Advanced and an actual 1500 PLC, but got the same IndexOutOfRangeException error:

Unhandled exception:  System.AggregateException: One or more errors occurred。 ---> System.IndexOutOfRangeException: Index out of array bounds。
   at S7.Net.Plc.<ReadStatusAsync>d__68.MoveNext()
   --- End of Internal Exception Stack Trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at S7View.S7API.GetStatus(Int16 plcId) Location D:\Projects\S7View\S7API.cs:Line 203
   at Test.Program.Main(String[] args) Location D:\Projects\S7View\Test\Program.cs:Line 15

image

Himmelt commented 1 year ago

Hi @mycroes , I have tested it with 1500 on PLCSIM Advanced and an actual 1500 PLC, but got the same IndexOutOfRangeException error:

Unhandled exception:  System.AggregateException: One or more errors occurred。 ---> System.IndexOutOfRangeException: Index out of array bounds。
   at S7.Net.Plc.<ReadStatusAsync>d__68.MoveNext()
   --- End of Internal Exception Stack Trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.Wait()
   at S7View.S7API.GetStatus(Int16 plcId) Location D:\Projects\S7View\S7API.cs:Line 203
   at Test.Program.Main(String[] args) Location D:\Projects\S7View\Test\Program.cs:Line 15

@mycroes I tested this function with source code in debug mode, and got this:

image image

mycroes commented 1 year ago

Wow, index 94 is way off, not sure how I ever calculated that. I started the unit test preparation yesterday, I intend to finish that today and I'll fix the index so this works. Thanks for testing!

mycroes commented 1 year ago

Hi @Himmelt, if you want to take this for another spin it should now be working! Let me know if it works, if it does I'll merge and release.

Himmelt commented 1 year ago

Hi @Himmelt, if you want to take this for another spin it should now be working! Let me know if it works, if it does I'll merge and release.

@mycroes It works !

I have tested S7300/S7400/S71200 running on PLCSIM with NetToPlcsim, and S71500 running on PLCSIM Advanced, and an actual S7-1511T-1 PLC, all works !

mycroes commented 1 year ago

Just released as v0.20.0!