using Shouldly; using Xunit; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; namespace ZB.MOM.WW.OtOpcUa.Driver.S7.IntegrationTests.S7_1500; /// /// #610 item 2 (S7-016): array write round trip against the python-snap7 S7-1500 profile. Skips /// cleanly when the sim is absent. Uses DB1 bytes 700+ (the profile's 1024-byte DB1 has no seed /// there), so the writes cannot disturb another test's seeds. Writes also require /// S7_SIM_ALLOW_WRITES=1. /// [Collection(Snap7ServerCollection.Name)] [Trait("Category", "Integration")] [Trait("Device", "S7_1500")] public sealed class S7_1500ArrayWriteTests(Snap7ServerFixture sim) { private static S7DriverOptions Options(string host, int port) => new() { Host = host, Port = port, CpuType = S7CpuType.S71500, Rack = 0, Slot = 0, Timeout = TimeSpan.FromSeconds(5), Probe = new S7ProbeOptions { Enabled = false }, RawTags = S7RawTags.Entries( new S7TagDefinition("I16Arr", "DB1.DBW700", S7DataType.Int16, Writable: true, ArrayCount: 4), new S7TagDefinition("F32Arr", "DB1.DBD720", S7DataType.Float32, Writable: true, ArrayCount: 3)), }; /// Writes a non-trivial Int16[4] and Float32[3], then reads each back element-for-element. [Fact] public async Task Array_write_then_read_round_trips_through_real_S7comm() { if (sim.SkipReason is not null) Assert.Skip(sim.SkipReason); // S7_SIM_ENDPOINT may point at a real CPU; writing needs an explicit opt-in (simulator runs only). if (Environment.GetEnvironmentVariable("S7_SIM_ALLOW_WRITES") != "1") Assert.Skip("Write test: set S7_SIM_ALLOW_WRITES=1 to allow writes to the endpoint under test (simulator only)."); await using var drv = new S7Driver(Options(sim.Host, sim.Port), "s7-arr-write"); await drv.InitializeAsync("{}", TestContext.Current.CancellationToken); var i16 = new short[] { 111, -222, 3333, -4444 }; var f32 = new[] { 1.5f, -2.25f, 1234.5f }; var res = await drv.WriteAsync( [new WriteRequest("I16Arr", i16), new WriteRequest("F32Arr", f32)], TestContext.Current.CancellationToken); res.Select(r => r.StatusCode).ShouldAllBe(c => c == 0u); var read = await drv.ReadAsync(["I16Arr", "F32Arr"], TestContext.Current.CancellationToken); read.Select(r => r.StatusCode).ShouldAllBe(c => c == 0u); ((short[])read[0].Value!).ShouldBe(i16); ((float[])read[1].Value!).ShouldBe(f32); } }