Skip to content

Commit acb5131

Browse files
fa-yoshinobuclaude
andcommitted
feat: replace ResolveProfileAsync with ProbeAllProfilesAsync; explicit OpenAndConnectAsync
- SlmpClient.ProbeAllProfilesAsync: probe all 4 frame/compat combinations, return all results (previously ResolveProfileAsync returned a single recommendation) - SlmpClient.OpenAndConnectAsync: now takes explicit frameType + compatibilityMode args instead of auto-detecting; callers choose profile from ProbeAllProfilesAsync results - SlmpModels: add SlmpProfileProbeResult record; remove SlmpNodeSearchInfo (unsupported on all tested PLCs) - SlmpEnums: remove NodeSearch / IpAddressSet command constants - SlmpProfileHeuristics: simplify to match new probe model - SlmpTargeting: minor adjustments - QueuedSlmpClient: update wrappers for new API - USER_GUIDE.md: document new connection flow - Tests: add SlmpParserTests coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ea83537 commit acb5131

File tree

9 files changed

+498
-265
lines changed

9 files changed

+498
-265
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ This list reflects device codes accepted by the parser and typed APIs. Actual av
5454
| Word devices (direct) | SD, D, W, SW, TN, STN, CN, Z, LZ, R, ZR, RD | Supported | `W/SW` use hexadecimal numbering. |
5555
| Long timer / counter families | LTS, LTC, LTN, LSTS, LSTC, LSTN, LCS, LCC, LCN | Supported (direct) | Some PLCs reject direct access; validate on the target. |
5656
| Extended Specification qualified devices | `Uxx\\Gyy`, `Uxx\\HGyy` | Supported via Extended Specification APIs | Direct `G/HG` access is not supported. |
57-
| Not supported | S, `Jn\\Xn` | Not supported | `S` is intentionally disabled; linked direct devices are out of scope. |
57+
| Link direct devices | `J□\\device` (e.g. `J2\\SW10`, `J1\\X10`) | Supported via Extended Specification APIs | CC-Link IE network device access. Use `ReadWordsExtendedAsync` / `ReadBitsExtendedAsync`. |
58+
| Not supported | S | Not supported | Step relay (`S`) is intentionally disabled. |
5859

5960
## Use Cases
6061

docsrc/user/USER_GUIDE.md

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,156 @@ var results = await Task.WhenAll(
174174

175175
---
176176

177+
## Supported Devices
178+
179+
Actual availability depends on PLC model and firmware.
180+
181+
### Bit Devices
182+
183+
Accessed via `ReadBitsAsync()` / `WriteBitsAsync()`.
184+
185+
| Symbol | Device Name | Address Base | Notes |
186+
|--------|-------------|-------------|-------|
187+
| SM | Special relay | Decimal | |
188+
| X | Input relay | Hex | |
189+
| Y | Output relay | Hex | |
190+
| M | Internal relay | Decimal | |
191+
| L | Latch relay | Decimal | |
192+
| F | Annunciator | Decimal | |
193+
| V | Edge relay | Decimal | |
194+
| B | Link relay | Hex | |
195+
| SB | Link special relay | Hex | |
196+
| DX | Direct input | Hex | |
197+
| DY | Direct output | Hex | |
198+
| TS | Timer contact | Decimal | |
199+
| TC | Timer coil | Decimal | |
200+
| STS | Retentive timer contact | Decimal | |
201+
| STC | Retentive timer coil | Decimal | |
202+
| CS | Counter contact | Decimal | |
203+
| CC | Counter coil | Decimal | |
204+
| LTS | Long timer contact | Decimal | iQ-R |
205+
| LTC | Long timer coil | Decimal | iQ-R |
206+
| LSTS | Long retentive timer contact | Decimal | iQ-R |
207+
| LSTC | Long retentive timer coil | Decimal | iQ-R |
208+
| LCS | Long counter contact | Decimal | iQ-R |
209+
| LCC | Long counter coil | Decimal | iQ-R |
210+
211+
> `S` (step relay) is present in the device code table but is intentionally disabled.
212+
213+
### Word Devices
214+
215+
Accessed via `ReadWordsRawAsync()` / `WriteWordsAsync()`.
216+
217+
| Symbol | Device Name | Address Base | Notes |
218+
|--------|-------------|-------------|-------|
219+
| SD | Special register | Decimal | |
220+
| D | Data register | Decimal | |
221+
| W | Link register | Hex | |
222+
| SW | Link special register | Hex | |
223+
| TN | Timer current value | Decimal | |
224+
| STN | Retentive timer current value | Decimal | |
225+
| CN | Counter current value | Decimal | |
226+
| Z | Index register | Decimal | |
227+
| LZ | Long index register | Decimal | iQ-R |
228+
| R | File register | Decimal | |
229+
| ZR | File register (extended) | Decimal | |
230+
| RD | Refresh data register | Decimal | |
231+
| LTN | Long timer current value | Decimal | iQ-R; prefer `ReadLongTimerAsync()` |
232+
| LSTN | Long retentive timer current value | Decimal | iQ-R; prefer `ReadLongRetentiveTimerAsync()` |
233+
| LCN | Long counter current value | Decimal | iQ-R |
234+
235+
### Long Timer / Retentive Timer Helpers (iQ-R)
236+
237+
```csharp
238+
var results = await client.ReadLongTimerAsync(headNo: 0, points: 4);
239+
foreach (var r in results)
240+
Console.WriteLine($"current={r.CurrentValue} set={r.SetValue} contact={r.Contact} coil={r.Coil}");
241+
```
242+
243+
| Method | Reads | Returns |
244+
|--------|-------|---------|
245+
| `ReadLongTimerAsync(headNo, points)` | LTN | `SlmpLongTimerResult[]` with `CurrentValue`, `SetValue`, `Contact` (LTS), `Coil` (LTC) |
246+
| `ReadLongRetentiveTimerAsync(headNo, points)` | LSTN | `SlmpLongTimerResult[]` for LST |
247+
| `ReadLtcStatesAsync(headNo, points)` | LTN → LTC coil | `bool[]` |
248+
| `ReadLtsStatesAsync(headNo, points)` | LTN → LTS contact | `bool[]` |
249+
| `ReadLstcStatesAsync(headNo, points)` | LSTN → LSTC coil | `bool[]` |
250+
| `ReadLstsStatesAsync(headNo, points)` | LSTN → LSTS contact | `bool[]` |
251+
252+
> Long timer / retentive timer set values (LT, LST) can only be read via these helpers, not as direct device codes.
253+
254+
### Module Buffer Access (Intelligent Module)
255+
256+
```csharp
257+
var values = await client.ReadWordsExtendedAsync(SlmpQualifiedDeviceParser.Parse(@"U3\G100"), 4, default);
258+
await client.WriteWordsExtendedAsync(SlmpQualifiedDeviceParser.Parse(@"U3\G100"), [1, 2, 3, 4], default);
259+
```
260+
261+
`U□` is the slot number in hex (e.g. `U3`, `U3E0`). Direct `G` / `HG` access without `U□\` prefix is not supported.
262+
263+
### Link Direct Device (CC-Link IE)
264+
265+
```csharp
266+
// Word read/write (subcommand 0x0080)
267+
var words = await client.ReadWordsExtendedAsync(SlmpQualifiedDeviceParser.Parse(@"J2\SW10"), 1, default);
268+
await client.WriteWordsExtendedAsync(SlmpQualifiedDeviceParser.Parse(@"J1\SW14"), [2], default);
269+
270+
// Bit read/write (subcommand 0x0081, 16-point units)
271+
var bits = await client.ReadBitsExtendedAsync(SlmpQualifiedDeviceParser.Parse(@"J1\X10"), 16, default);
272+
await client.WriteBitsExtendedAsync(SlmpQualifiedDeviceParser.Parse(@"J1\X11"), [true], default);
273+
```
274+
275+
Known limitations:
276+
277+
| Device | End Code | Note |
278+
|--------|----------|------|
279+
| `J1\B0` (B device) | `0x4031` | Not supported on CC-Link IE; GOT returns the same error |
280+
281+
---
282+
283+
## Other Station Routing (他局指定)
284+
285+
By default, requests target the directly connected PLC (self station). To route to another station, set `TargetAddress` on the client.
286+
287+
```csharp
288+
// Other station: Network 1, Station 1
289+
client.TargetAddress = new SlmpTargetAddress(Network: 0x01, Station: 0x01);
290+
291+
// Full specification (network, station, moduleIo, multidrop)
292+
client.TargetAddress = new SlmpTargetAddress(0x01, 0x01, 0x03FF, 0x00);
293+
```
294+
295+
`SlmpTargetAddress` fields:
296+
297+
| Field | Default | Description |
298+
|-------|---------|-------------|
299+
| `Network` | `0x00` | Network number (`0x00` = local network) |
300+
| `Station` | `0xFF` | Station number (`0xFF` = control CPU of self station) |
301+
| `ModuleIo` | `0x03FF` | Module I/O No. |
302+
| `Multidrop` | `0x00` | Multidrop station No. (`0x00` = no multidrop) |
303+
304+
Common `ModuleIo` values:
305+
306+
| Value | Description |
307+
|-------|-------------|
308+
| `0x03FF` | Own station / control CPU (default) |
309+
| `0x03E0` | Multiple CPU No.1 / Remote head No.1 |
310+
| `0x03E1` | Multiple CPU No.2 / Remote head No.2 |
311+
| `0x03E2` | Multiple CPU No.3 |
312+
| `0x03E3` | Multiple CPU No.4 |
313+
| `0x03D0` | Control system CPU (redundant) |
314+
| `0x03D1` | Standby system CPU (redundant) |
315+
316+
`SlmpTargetParser.ParseNamed` shorthand:
317+
318+
| Format | Example | Description |
319+
|--------|---------|-------------|
320+
| `"SELF"` | `"SELF"` | Own station, control CPU |
321+
| `"SELF-CPU1"` .. `"SELF-CPU4"` | `"SELF-CPU2"` | Own station, Multiple CPU No. |
322+
| `"NWx-STy"` | `"NW1-ST3"` | Network x, Station y |
323+
| `"NAME,NW,ST,IO,MD"` | `"PLC2,1,3,0x03FF,0"` | Full specification |
324+
325+
---
326+
177327
## Error Handling
178328

179329
| Exception | Condition |

src/PlcComm.Slmp/QueuedSlmpClient.cs

Lines changed: 163 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ public async Task ExecuteAsync(Func<SlmpClient, Task> operation, CancellationTok
111111
}
112112
}
113113

114-
/// <inheritdoc cref="SlmpClient.ResolveProfileAsync"/>
115-
public Task<SlmpProfileRecommendation> ResolveProfileAsync(CancellationToken cancellationToken = default)
116-
=> ExecuteAsync(client => client.ResolveProfileAsync(cancellationToken), cancellationToken);
114+
/// <inheritdoc cref="SlmpClient.ProbeAllProfilesAsync"/>
115+
public Task<IReadOnlyList<SlmpProfileProbeResult>> ProbeAllProfilesAsync(CancellationToken cancellationToken = default)
116+
=> ExecuteAsync(client => client.ProbeAllProfilesAsync(cancellationToken), cancellationToken);
117117

118118
/// <inheritdoc cref="SlmpClient.ReadTypeNameAsync"/>
119119
public Task<SlmpTypeNameInfo> ReadTypeNameAsync(CancellationToken cancellationToken = default)
@@ -191,6 +191,42 @@ public Task WriteBlockAsync(
191191
)
192192
=> ExecuteAsync(client => client.WriteBlockAsync(wordBlocks, bitBlocks, options, cancellationToken), cancellationToken);
193193

194+
/// <inheritdoc cref="SlmpClient.ReadBitsExtendedAsync"/>
195+
public Task<bool[]> ReadBitsExtendedAsync(
196+
SlmpQualifiedDeviceAddress device,
197+
ushort points,
198+
SlmpExtensionSpec extension,
199+
CancellationToken cancellationToken = default
200+
)
201+
=> ExecuteAsync(client => client.ReadBitsExtendedAsync(device, points, extension, cancellationToken), cancellationToken);
202+
203+
/// <inheritdoc cref="SlmpClient.WriteBitsExtendedAsync"/>
204+
public Task WriteBitsExtendedAsync(
205+
SlmpQualifiedDeviceAddress device,
206+
IReadOnlyList<bool> values,
207+
SlmpExtensionSpec extension,
208+
CancellationToken cancellationToken = default
209+
)
210+
=> ExecuteAsync(client => client.WriteBitsExtendedAsync(device, values, extension, cancellationToken), cancellationToken);
211+
212+
/// <inheritdoc cref="SlmpClient.ReadWordsExtendedAsync"/>
213+
public Task<ushort[]> ReadWordsExtendedAsync(
214+
SlmpQualifiedDeviceAddress device,
215+
ushort points,
216+
SlmpExtensionSpec extension,
217+
CancellationToken cancellationToken = default
218+
)
219+
=> ExecuteAsync(client => client.ReadWordsExtendedAsync(device, points, extension, cancellationToken), cancellationToken);
220+
221+
/// <inheritdoc cref="SlmpClient.WriteWordsExtendedAsync"/>
222+
public Task WriteWordsExtendedAsync(
223+
SlmpQualifiedDeviceAddress device,
224+
IReadOnlyList<ushort> values,
225+
SlmpExtensionSpec extension,
226+
CancellationToken cancellationToken = default
227+
)
228+
=> ExecuteAsync(client => client.WriteWordsExtendedAsync(device, values, extension, cancellationToken), cancellationToken);
229+
194230
/// <inheritdoc cref="SlmpClient.ReadRandomExtAsync"/>
195231
public Task<(ushort[] WordValues, uint[] DwordValues)> ReadRandomExtAsync(
196232
IReadOnlyList<(SlmpQualifiedDeviceAddress Device, SlmpExtensionSpec Extension)> wordDevices,
@@ -214,6 +250,130 @@ public Task WriteRandomBitsExtAsync(
214250
)
215251
=> ExecuteAsync(client => client.WriteRandomBitsExtAsync(bitEntries, cancellationToken), cancellationToken);
216252

253+
/// <inheritdoc cref="SlmpClient.ReadLongTimerAsync"/>
254+
public Task<SlmpLongTimerResult[]> ReadLongTimerAsync(int headNo = 0, int points = 1, CancellationToken cancellationToken = default)
255+
=> ExecuteAsync(client => client.ReadLongTimerAsync(headNo, points, cancellationToken), cancellationToken);
256+
257+
/// <inheritdoc cref="SlmpClient.ReadLongRetentiveTimerAsync"/>
258+
public Task<SlmpLongTimerResult[]> ReadLongRetentiveTimerAsync(int headNo = 0, int points = 1, CancellationToken cancellationToken = default)
259+
=> ExecuteAsync(client => client.ReadLongRetentiveTimerAsync(headNo, points, cancellationToken), cancellationToken);
260+
261+
/// <inheritdoc cref="SlmpClient.ReadLtcStatesAsync"/>
262+
public Task<bool[]> ReadLtcStatesAsync(int headNo = 0, int points = 1, CancellationToken cancellationToken = default)
263+
=> ExecuteAsync(client => client.ReadLtcStatesAsync(headNo, points, cancellationToken), cancellationToken);
264+
265+
/// <inheritdoc cref="SlmpClient.ReadLtsStatesAsync"/>
266+
public Task<bool[]> ReadLtsStatesAsync(int headNo = 0, int points = 1, CancellationToken cancellationToken = default)
267+
=> ExecuteAsync(client => client.ReadLtsStatesAsync(headNo, points, cancellationToken), cancellationToken);
268+
269+
/// <inheritdoc cref="SlmpClient.ReadLstcStatesAsync"/>
270+
public Task<bool[]> ReadLstcStatesAsync(int headNo = 0, int points = 1, CancellationToken cancellationToken = default)
271+
=> ExecuteAsync(client => client.ReadLstcStatesAsync(headNo, points, cancellationToken), cancellationToken);
272+
273+
/// <inheritdoc cref="SlmpClient.ReadLstsStatesAsync"/>
274+
public Task<bool[]> ReadLstsStatesAsync(int headNo = 0, int points = 1, CancellationToken cancellationToken = default)
275+
=> ExecuteAsync(client => client.ReadLstsStatesAsync(headNo, points, cancellationToken), cancellationToken);
276+
277+
/// <inheritdoc cref="SlmpClient.ReadArrayLabelsAsync"/>
278+
public Task<SlmpLabelArrayReadResult[]> ReadArrayLabelsAsync(
279+
IReadOnlyList<SlmpLabelArrayReadPoint> points,
280+
IReadOnlyList<string>? abbreviationLabels = null,
281+
CancellationToken cancellationToken = default)
282+
=> ExecuteAsync(client => client.ReadArrayLabelsAsync(points, abbreviationLabels, cancellationToken), cancellationToken);
283+
284+
/// <inheritdoc cref="SlmpClient.WriteArrayLabelsAsync"/>
285+
public Task WriteArrayLabelsAsync(
286+
IReadOnlyList<SlmpLabelArrayWritePoint> points,
287+
IReadOnlyList<string>? abbreviationLabels = null,
288+
CancellationToken cancellationToken = default)
289+
=> ExecuteAsync(client => client.WriteArrayLabelsAsync(points, abbreviationLabels, cancellationToken), cancellationToken);
290+
291+
/// <inheritdoc cref="SlmpClient.ReadRandomLabelsAsync"/>
292+
public Task<SlmpLabelRandomReadResult[]> ReadRandomLabelsAsync(
293+
IReadOnlyList<string> labels,
294+
IReadOnlyList<string>? abbreviationLabels = null,
295+
CancellationToken cancellationToken = default)
296+
=> ExecuteAsync(client => client.ReadRandomLabelsAsync(labels, abbreviationLabels, cancellationToken), cancellationToken);
297+
298+
/// <inheritdoc cref="SlmpClient.WriteRandomLabelsAsync"/>
299+
public Task WriteRandomLabelsAsync(
300+
IReadOnlyList<SlmpLabelRandomWritePoint> points,
301+
IReadOnlyList<string>? abbreviationLabels = null,
302+
CancellationToken cancellationToken = default)
303+
=> ExecuteAsync(client => client.WriteRandomLabelsAsync(points, abbreviationLabels, cancellationToken), cancellationToken);
304+
305+
/// <inheritdoc cref="SlmpClient.MemoryReadWordsAsync"/>
306+
public Task<ushort[]> MemoryReadWordsAsync(uint headAddress, ushort wordLength, CancellationToken cancellationToken = default)
307+
=> ExecuteAsync(client => client.MemoryReadWordsAsync(headAddress, wordLength, cancellationToken), cancellationToken);
308+
309+
/// <inheritdoc cref="SlmpClient.MemoryWriteWordsAsync"/>
310+
public Task MemoryWriteWordsAsync(uint headAddress, IReadOnlyList<ushort> values, CancellationToken cancellationToken = default)
311+
=> ExecuteAsync(client => client.MemoryWriteWordsAsync(headAddress, values, cancellationToken), cancellationToken);
312+
313+
/// <inheritdoc cref="SlmpClient.ExtendUnitReadBytesAsync"/>
314+
public Task<byte[]> ExtendUnitReadBytesAsync(uint headAddress, ushort byteLength, ushort moduleNo, CancellationToken cancellationToken = default)
315+
=> ExecuteAsync(client => client.ExtendUnitReadBytesAsync(headAddress, byteLength, moduleNo, cancellationToken), cancellationToken);
316+
317+
/// <inheritdoc cref="SlmpClient.ExtendUnitReadWordsAsync"/>
318+
public Task<ushort[]> ExtendUnitReadWordsAsync(uint headAddress, ushort wordLength, ushort moduleNo, CancellationToken cancellationToken = default)
319+
=> ExecuteAsync(client => client.ExtendUnitReadWordsAsync(headAddress, wordLength, moduleNo, cancellationToken), cancellationToken);
320+
321+
/// <inheritdoc cref="SlmpClient.ExtendUnitReadWordAsync"/>
322+
public Task<ushort> ExtendUnitReadWordAsync(uint headAddress, ushort moduleNo, CancellationToken cancellationToken = default)
323+
=> ExecuteAsync(client => client.ExtendUnitReadWordAsync(headAddress, moduleNo, cancellationToken), cancellationToken);
324+
325+
/// <inheritdoc cref="SlmpClient.ExtendUnitReadDWordAsync"/>
326+
public Task<uint> ExtendUnitReadDWordAsync(uint headAddress, ushort moduleNo, CancellationToken cancellationToken = default)
327+
=> ExecuteAsync(client => client.ExtendUnitReadDWordAsync(headAddress, moduleNo, cancellationToken), cancellationToken);
328+
329+
/// <inheritdoc cref="SlmpClient.ExtendUnitWriteBytesAsync"/>
330+
public Task ExtendUnitWriteBytesAsync(uint headAddress, ushort moduleNo, ReadOnlyMemory<byte> data, CancellationToken cancellationToken = default)
331+
=> ExecuteAsync(client => client.ExtendUnitWriteBytesAsync(headAddress, moduleNo, data, cancellationToken), cancellationToken);
332+
333+
/// <inheritdoc cref="SlmpClient.ExtendUnitWriteWordsAsync"/>
334+
public Task ExtendUnitWriteWordsAsync(uint headAddress, ushort moduleNo, IReadOnlyList<ushort> values, CancellationToken cancellationToken = default)
335+
=> ExecuteAsync(client => client.ExtendUnitWriteWordsAsync(headAddress, moduleNo, values, cancellationToken), cancellationToken);
336+
337+
/// <inheritdoc cref="SlmpClient.ExtendUnitWriteWordAsync"/>
338+
public Task ExtendUnitWriteWordAsync(uint headAddress, ushort moduleNo, ushort value, CancellationToken cancellationToken = default)
339+
=> ExecuteAsync(client => client.ExtendUnitWriteWordAsync(headAddress, moduleNo, value, cancellationToken), cancellationToken);
340+
341+
/// <inheritdoc cref="SlmpClient.ExtendUnitWriteDWordAsync"/>
342+
public Task ExtendUnitWriteDWordAsync(uint headAddress, ushort moduleNo, uint value, CancellationToken cancellationToken = default)
343+
=> ExecuteAsync(client => client.ExtendUnitWriteDWordAsync(headAddress, moduleNo, value, cancellationToken), cancellationToken);
344+
345+
/// <inheritdoc cref="SlmpClient.CpuBufferReadWordsAsync"/>
346+
public Task<ushort[]> CpuBufferReadWordsAsync(uint headAddress, ushort wordLength, CancellationToken cancellationToken = default)
347+
=> ExecuteAsync(client => client.CpuBufferReadWordsAsync(headAddress, wordLength, cancellationToken), cancellationToken);
348+
349+
/// <inheritdoc cref="SlmpClient.CpuBufferReadBytesAsync"/>
350+
public Task<byte[]> CpuBufferReadBytesAsync(uint headAddress, ushort byteLength, CancellationToken cancellationToken = default)
351+
=> ExecuteAsync(client => client.CpuBufferReadBytesAsync(headAddress, byteLength, cancellationToken), cancellationToken);
352+
353+
/// <inheritdoc cref="SlmpClient.CpuBufferReadWordAsync"/>
354+
public Task<ushort> CpuBufferReadWordAsync(uint headAddress, CancellationToken cancellationToken = default)
355+
=> ExecuteAsync(client => client.CpuBufferReadWordAsync(headAddress, cancellationToken), cancellationToken);
356+
357+
/// <inheritdoc cref="SlmpClient.CpuBufferReadDWordAsync"/>
358+
public Task<uint> CpuBufferReadDWordAsync(uint headAddress, CancellationToken cancellationToken = default)
359+
=> ExecuteAsync(client => client.CpuBufferReadDWordAsync(headAddress, cancellationToken), cancellationToken);
360+
361+
/// <inheritdoc cref="SlmpClient.CpuBufferWriteWordsAsync"/>
362+
public Task CpuBufferWriteWordsAsync(uint headAddress, IReadOnlyList<ushort> values, CancellationToken cancellationToken = default)
363+
=> ExecuteAsync(client => client.CpuBufferWriteWordsAsync(headAddress, values, cancellationToken), cancellationToken);
364+
365+
/// <inheritdoc cref="SlmpClient.CpuBufferWriteBytesAsync"/>
366+
public Task CpuBufferWriteBytesAsync(uint headAddress, ReadOnlyMemory<byte> data, CancellationToken cancellationToken = default)
367+
=> ExecuteAsync(client => client.CpuBufferWriteBytesAsync(headAddress, data, cancellationToken), cancellationToken);
368+
369+
/// <inheritdoc cref="SlmpClient.CpuBufferWriteWordAsync"/>
370+
public Task CpuBufferWriteWordAsync(uint headAddress, ushort value, CancellationToken cancellationToken = default)
371+
=> ExecuteAsync(client => client.CpuBufferWriteWordAsync(headAddress, value, cancellationToken), cancellationToken);
372+
373+
/// <inheritdoc cref="SlmpClient.CpuBufferWriteDWordAsync"/>
374+
public Task CpuBufferWriteDWordAsync(uint headAddress, uint value, CancellationToken cancellationToken = default)
375+
=> ExecuteAsync(client => client.CpuBufferWriteDWordAsync(headAddress, value, cancellationToken), cancellationToken);
376+
217377
/// <inheritdoc cref="SlmpClient.RegisterMonitorDevicesAsync"/>
218378
public Task RegisterMonitorDevicesAsync(
219379
IReadOnlyList<SlmpDeviceAddress> wordDevices,

0 commit comments

Comments
 (0)