Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set PLC-time through code #502

Closed
SmackyPappelroy opened this issue Aug 17, 2023 · 13 comments · Fixed by #507
Closed

Set PLC-time through code #502

SmackyPappelroy opened this issue Aug 17, 2023 · 13 comments · Fixed by #507

Comments

@SmackyPappelroy
Copy link

Is it possible to implement a method to set the PLC-time? That would be a great feature to have in a logging application so the clocks are synchronized. I have seen Wireshark captures of how to set the clock. That might provide some guidance.

@mycroes
Copy link
Member

mycroes commented Aug 17, 2023

Yes. Are those captures from the Wireshark page about the S7 dissector? I think I might have seen them as well...

I recently implemented PLC status reading, which uses the SZL subset of communication, I believe system time uses SZL commands as well.

@SmackyPappelroy
Copy link
Author

SmackyPappelroy commented Aug 17, 2023

I have seen that you implemented that great feature. I am not sure that the set clock function is an SZL protocol function, by just browsing the wireshark capture, SZL seems to be related to diagnostic and status data FROM the PLC. Here is the link to the wireshark captures: https://wiki.wireshark.org/S7comm.
FYI I found this manual where it describes the SZL-id and the index for all the functions starting on page 151 in this manual: "Instructions List: S7–300 Programmable Controller"
After further digging I found this on GitHub as well https://github.com/moki-ics/s7commwireshark

@mycroes
Copy link
Member

mycroes commented Aug 23, 2023

Just started on this. Will start by implementing clock read, then I'll add clock write. I hope to have this finished within a few days.

@SmackyPappelroy
Copy link
Author

SmackyPappelroy commented Aug 24, 2023

Perfect. I tried to create a set clock method.
I never got it to work, I just got a socket exception. But it might be something useful for you.

``public static void WriteClockRequest(System.IO.MemoryStream stream, System.DateTime dateTime)
{
// Parameter head
stream.Write(new byte[] { 0x32, 0x07, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x08, 0x00, 0x0e });

// Parameter
stream.Write(new byte[] { 0x00, 0x01, 0x12 });
stream.WriteByte(0x04); // Parameter length
stream.WriteByte(0x11); // Method
stream.WriteByte(0x47); // Type / function group
stream.WriteByte(0x02); // Subfunction
stream.WriteByte(0x00); // Sequence number


// Data
stream.WriteByte(0xff); // Return code
stream.WriteByte(0x09); // Transport size
stream.Write(new byte[] { 0x00, 0x0a }); // Length

stream.WriteByte(0x00); // Reserved
var s7DateTime = DateTime.ToByteArray(dateTime);
stream.Write(s7DateTime); // Date and time

}``

@mycroes
Copy link
Member

mycroes commented Aug 29, 2023

Hi @SmackyPappelroy,

I think what's wrong is your stream.WriteByte(0x00); // Reserved. That's actually part of the date value, so now your data doesn't match the protocol. That's also why I recently started adding some unit tests and the infrastructure to test full communication cycles, which easily exposes problems like these.

Anyway, in the meantime I added clock read in #507, you can take that for a spin and see if it works as expected. I'll be adding clock write soon.

@SmackyPappelroy
Copy link
Author

Hello @mycroes. I tried your code on a simulated S7300 and it worked as expected.
I also tried against a real S71500 CPU but then i got an exception:

System.Exception
HResult=0x80131500
Message=Response from PLC indicates error 0x8104.
Source=S7.Net
StackTrace:
at S7.Net.Plc.ParseClockReadResponse(Byte[] message) in C:\temp\temp\S7.Net\Plc.Clock.cs:line 41
at S7.Net.Plc.ReadClock() in C:\temp\temp\S7.Net\PlcSynchronous.cs:line 504
at Program.

$(String[] args) in C:\temp\temp\testing\Program.cs:line 7

This exception was originally thrown at this call stack:
S7.Net.Plc.ParseClockReadResponse(byte[]) in Plc.Clock.cs
S7.Net.Plc.ReadClock() in PlcSynchronous.cs
Program.

$(string[]) in Program.cs

I am not sure why this happens. If I can be of any assistance, let me know. I have access to real Siemens PLCs, so I can test changes.

@mycroes
Copy link
Member

mycroes commented Aug 30, 2023

Could you provide the contents of message in Plc.Clock.cs ParseClockReadResponse? I'll also add a new exception type that includes the data by default so it's apparent from the exception.

@SmackyPappelroy
Copy link
Author

pduErr = 33028 and message is:

Byte

50
7
0
0
0
0
0
12
0
4
0
1
18
8
18
135
1
0
0
0
129
4
10
0
0
0

@mycroes
Copy link
Member

mycroes commented Aug 30, 2023

I'm not sure if this maybe just doesn't work on S7 1500. I've been comparing my code to st-one-io/nodes7 and from what I see it's producing the same data. The message you received from the PLC seems to be a valid response message to the request (all of the data seems to indicate this is indeed a response to the get time request that was sent), it just doesn't have actual time data but the error fields are all set. The returned error code is actually defined in nodes7:

"33028": "This service is not implemented on the module or a frame error was reported",

That does seem to indicate it might just not be available on S7 1500. If you can get the time from TIA portal there's probably a different communication method to do that.

I'll continue on adding this feature though, but I guess it might only work for 300/400 PLC's.

@SmackyPappelroy
Copy link
Author

I haven't been able to get it to work on an S7-1500. The S7COMM filter for WireShark is mainly for S7300/S7400 CPUs so I haven't been able to capture anything useful when I try to do a clock read in TIA Portal. Nevertheless it is a good feature to have even if we can't figure out how to do it for an S7-1500 CPU.

@mycroes
Copy link
Member

mycroes commented Sep 4, 2023

Clock write support is there as well now. I guess it only works for S7 300 / S7 400, but if you could give that a spin that would be nice. I didn't expand the exception messages yet, I haven't decided on including that in the PR or as a separate PR. Looking forward to your response.

@SmackyPappelroy
Copy link
Author

I have tried both the sync and the async methods against an S7300 and it worked perfectly.

I have also tried against both a real S71500 and a simulated. That did not work, I only get this exception:

System.Exception
HResult=0x80131500
Message=Response from PLC indicates error 0x8104.
Source=S7.Net
StackTrace:
at S7.Net.Plc.AssertPduResult(Byte[] message) in C:\Test\S7.Net\Plc.Clock.cs:line 82
at S7.Net.Plc.ParseClockWriteResponse(Byte[] message) in C:\Test\S7.Net\Plc.Clock.cs:line 71
at S7.Net.Plc.WriteClock(DateTime value) in C:\Test\S7.Net\PlcSynchronous.cs:line 516
at Program.

$(String[] args) in C:\Test\ConsoleApp1\Program.cs:line 8

This exception was originally thrown at this call stack:
S7.Net.Plc.AssertPduResult(byte[]) in Plc.Clock.cs
S7.Net.Plc.ParseClockWriteResponse(byte[]) in Plc.Clock.cs
S7.Net.Plc.WriteClock(System.DateTime) in PlcSynchronous.cs
Program.

$(string[]) in Program.cs

@mycroes
Copy link
Member

mycroes commented Sep 5, 2023

Thanks a lot for testing, I'll try to release this soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants