Closed SmackyPappelroy closed 11 months ago
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.
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
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.
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
}``
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.
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.
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.
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.
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.
pduErr = 33028 and message is:
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
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.
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.
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.
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.
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.
Thanks a lot for testing, I'll try to release this soon.
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.