Repository navigation
Generic client: single sampling scheduler and monitored item fixes - #36
viacheslauK wants to merge 13 commits into
Conversation
…rence and usage steps
…ructor to prevent use after destruction
8e76917 to
c3752de
Compare
…ependent, drop macOS skips
…#41) The device now holds only defaults for new blocks: DefaultTimestampMode and DefaultSamplingInterval. Each MonitoredItem has its own TimestampMode and SamplingInterval properties, which start from those defaults. None of these properties is part of a config. They exist only as properties after the object is created.
| sampler.stop(); | ||
| } | ||
|
|
||
| PropertyObjectPtr OpcuaGenericClientDeviceImpl::createDefaultConfig() |
There was a problem hiding this comment.
The removal of any property (even in config) should be explicitly stated in the PR description, as it's a breaking change.
| server's own sampling and publishing settings do not apply. Every successful read publishes a sample, | ||
| even when the value has not changed — there is no deadband or change filter. |
There was a problem hiding this comment.
Does this apply even if the timestamps are equal? We should probably avoid sending packets with repeated timestamps.
There was a problem hiding this comment.
Yes, even if the timestamps are equal
|
|
||
| const auto samplingInterval = | ||
| readProperty<Int, IInteger>(objPtr, PROPERTY_NAME_OPCUA_DEFAULT_SAMPLING_INTERVAL, DEFAULT_OPCUA_MIFB_SAMPLING_INTERVAL); | ||
| if (samplingInterval <= 0 || samplingInterval > static_cast<Int>(std::numeric_limits<uint32_t>::max())) |
There was a problem hiding this comment.
This should be added as a min/max attribute of the SamplingInterval property.
| { | ||
| std::unique_lock lock(mutex); | ||
| items.erase(std::remove_if(items.begin(), items.end(), [item](const Entry& e) { return e.item == item; }), items.end()); | ||
| inFlightCv.wait(lock, [this, item] { return inFlight != item; }); |
There was a problem hiding this comment.
This can deadlock during removed() if reconnection happens at the same time as destruction.
| .setUnit(Unit("s", -1, "seconds", "time")) | ||
| .setTickResolution(Ratio(1, 1'000'000)) | ||
| .setOrigin("1970-01-01T00:00:00Z") | ||
| .setName("Time") |
There was a problem hiding this comment.
We should not set the name of data descriptors that are not struct types.
| @@ -418,7 +465,7 @@ void OpcUaMonitoredItemFbImpl::createSignal() | |||
|
|
|||
| void OpcUaMonitoredItemFbImpl::reconfigureSignal(const FbConfig& prevConfig) | |||
There was a problem hiding this comment.
Seems like prevConfig is now an usused parameter.
| | `DeviceNodeIDType` | Selection | `1` — `String` | | ||
| | `DeviceNodeIDString` | String | `""` | | ||
| | `DeviceNodeIDNumeric` | Int | `0` | | ||
| | `DeviceNamespaceIndex` | Int | `0` | |
There was a problem hiding this comment.
As discussed, these should be a fallback in case the DeviceSet is not found / has no child objects of DeviceType.
Summary
Replaces the reader thread that each
OpcUaMonitoredItemFbImplused to own with oneSamplingSchedulerper device, and fixes several monitored-item defects found along the way.Changes
SamplingScheduler(new) drives every monitored item of a device from one thread, each item keeping its own deadline.OpcUaDataValue::isDateTime(); DateTime values now build a packet and are read asUA_DateTimeinstead ofreadScalar<UA_Int64>, including theUtcTimesubtype.SamplingIntervalrejects negative and above-uint32_tvalues; reads reject a null value, report a failed packet build, and catchstd::exception/...beyondOpcUaException.test_sampling_scheduler.cpp; device and monitored-item suites extended; test server publishes.dtand.utcnodes;USAGE.mdadds a property reference and walkthrough.