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

Implemented JDS protocol startup requests and basic communication #55

Merged
merged 62 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
68665a5
JdsService | Implemented JDS protocol startup requests
Minyewoo Mar 11, 2024
f9074cb
hmi_networking | Exported newly created classes
Minyewoo Mar 12, 2024
59d0912
hmi_networking | updated exports
Minyewoo Mar 12, 2024
1268af8
UpdateCacheFromPointConfigs | Incapsulated cache update functionality
Minyewoo Mar 12, 2024
a19ddfe
JdsService | moved to protocol directory
Minyewoo Mar 12, 2024
47be350
UpdatePointsCacheFromJdsService | Added config request into apply fun…
Minyewoo Mar 12, 2024
68cc34d
DsClientReal | requesting point configs on connection resumes
Minyewoo Mar 12, 2024
f16cc59
JdsServiceStartup | Added cache update
Minyewoo Mar 12, 2024
90f8848
JDS protocol | refactored, added documentation
Minyewoo Mar 13, 2024
03ae771
JdsDataType | fixed naming for enum members
Minyewoo Mar 13, 2024
9665250
TransportEndpoint | Handled possible error from connection interruptions
Minyewoo Mar 13, 2024
a03a678
TransportEndpoint | Added test for exchange method
Minyewoo Mar 13, 2024
e4ac953
InternetEndpoint | Renamed to WebAddress
Minyewoo Mar 14, 2024
5ebcf50
Tcp | Added connection timeout
Minyewoo Mar 14, 2024
a6b5045
JDS | Added tests and fixes they caused
Minyewoo Mar 14, 2024
4a78842
JdsService | Reworked
Minyewoo Mar 15, 2024
f9c5ca8
Fixed test data due to DsDataPoint changes
Minyewoo Mar 18, 2024
6fcbead
JdsService | Added tests
Minyewoo Mar 18, 2024
7658afb
JdsService | Added tests on Err result
Minyewoo Mar 18, 2024
1835e65
Added tests for JdsService utility classes
Minyewoo Mar 18, 2024
c0f3c63
DsSend | Fixed point miss if DsClient not listening yet
Minyewoo Mar 21, 2024
8ac9e25
DsClientCache | Added filtered caches
Minyewoo Mar 21, 2024
1da2227
JdsServiceStartup | Added auth retries
Minyewoo Mar 21, 2024
763d64d
JdsServiceStartup | Updated test
Minyewoo Mar 22, 2024
e11988b
pubspec | bumped hmi_core version
Minyewoo Mar 22, 2024
7d0e026
JdsServiceStartup | Removed twin points request from run method
Minyewoo Mar 25, 2024
4c3a518
JdsService | Add route to robustly configure point location
Minyewoo Mar 26, 2024
b60d735
JdsService | Fixed imports
Minyewoo Mar 26, 2024
e95eeaa
DsSend | Added stream buffering before request sending
Minyewoo Mar 26, 2024
974c122
DsClientReal | Collected receivers to list to avoid concurrent modifi…
Minyewoo Mar 26, 2024
31cc042
JdsServiceStartupOnReconnect | changed reconnect callback
Minyewoo Mar 29, 2024
5590eff
JdsServiceStartupOnReconnect | fixed wrong connection status displaying
Minyewoo Mar 29, 2024
12e7132
JdsServiceStartupOnReconnect | Made startup cancellable
Minyewoo Mar 29, 2024
1a00834
JdsServiceStartupOnReconnect | Used cancellable completer instead of …
Minyewoo Mar 29, 2024
42e90c4
JdsServiceStartupOnReconnect | Now not starting startup process when …
Minyewoo Mar 30, 2024
89ed64f
DsClientReal | Made caching conditionless
Minyewoo Mar 30, 2024
77e8127
JdsServiceStartup | Removed caching from server config
Minyewoo Mar 30, 2024
4e9ed80
JdsServiceStartup | Removed obsolete params
Minyewoo Mar 30, 2024
58b189b
JdsServiceStartup | Removed obsolete params from constructor
Minyewoo Mar 30, 2024
a5ba839
JdsServiceStartupOnReconnect | reworked startup mechanism
Minyewoo Mar 30, 2024
ec71ab7
JdsServiceStartupOnReconnect | workaround for startup not starting on…
Minyewoo Mar 30, 2024
862c138
JdsServiceStartupOnReconnect | updated
Minyewoo Apr 2, 2024
ec058ec
JdsPointConfig | made address optional
Minyewoo Apr 2, 2024
bd17a52
JdsServiceStartupOnReconnect | fixed initial state for _isConnected
Minyewoo Apr 2, 2024
e3b76a7
JdsLine | removed GI request from requestAll method
Minyewoo Apr 2, 2024
e521713
JdsLine | Made proper parsing error message
Minyewoo Apr 3, 2024
28bda98
JdsLine | fixed error messages
Minyewoo Apr 3, 2024
69eb5f7
JdsLine | extexded log message
Minyewoo Apr 3, 2024
a9504af
JdsLine | commented out bytes debug logs
Minyewoo Apr 3, 2024
b3661f6
JdsLine | commented out bytes debug logs
Minyewoo Apr 3, 2024
a127ff8
DsClientReal | upgraded log calls
Minyewoo Apr 3, 2024
29ac631
common | Upgraded logs
Minyewoo Apr 4, 2024
fe5cc2a
DsLineSocket | supressed log of bytes
Minyewoo Apr 4, 2024
2847d65
JdsServiceStartupOnReconnect | supressed log spam
Minyewoo Apr 4, 2024
fe82c32
DsSend | reduced default responseTimeout
Minyewoo Apr 10, 2024
04c4033
DsSend | replaced seconds count with duration for responseTimeout
Minyewoo Apr 11, 2024
04c7a86
JdsService | Reduced response timeout for all of the requests
Minyewoo Apr 11, 2024
cd8bd01
JdsService | Made response timeout configurable
Minyewoo Apr 11, 2024
dc81ac1
JdsServiceStartupOnReconnect | made isConnected status configurable
Minyewoo Apr 11, 2024
9c3f099
JdsServiceStartupOnReconnect | switched some log messages to debug
Minyewoo Apr 11, 2024
c6d49ea
DsClientCache | changed caching to persist points with full path as key
Minyewoo Apr 17, 2024
93687b9
common | fixed cache tests due to storing mechanism update
Minyewoo Apr 22, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions lib/hmi_networking.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,28 @@ export 'src/core/ds_client/cache/delayed/ds_client_delayed_cache.dart';
export 'src/core/ds_client/cache/file/ds_cache_file.dart';
export 'src/core/ds_client/cache/file/ds_client_file_cache.dart';
export 'src/core/ds_client/cache/memory/ds_client_memory_cache.dart';
export 'src/core/ds_client/cache/filtered/ds_client_filtered_cache.dart';
export 'src/core/jds_service/update_cache_from_jds_service.dart';
export 'src/core/jds_service/jds_service_startup_on_reconnect.dart';
export 'src/core/jds_service/jds_service.dart';
export 'src/core/jds_service/jds_service_startup.dart';
export 'src/core/jds_service/jds_service_route.dart';
export 'src/core/jds_service/jds_point_config/jds_point_config.dart';
export 'src/core/jds_service/jds_point_config/jds_point_configs.dart';
export 'src/core/jds_service/jds_point_config/ds_access_mode.dart';
export 'src/core/jds_service/jds_point_config/ds_filters.dart';
export 'src/core/jds_service/jds_point_config/ds_point_address.dart';
export 'src/core/line_socket/ds_line_socket.dart';
export 'src/core/line_socket/line_socket.dart';
export 'src/core/ds_data_stream_extract.dart';
export 'src/core/entities/ds_data_point_extracted.dart';
export 'src/core/ds_send.dart';
export 'src/core/non_repetitive_stream.dart';
export 'src/core/entities/double_container.dart';
export 'src/core/entities/network_operation_state.dart';
export 'src/core/entities/data_object.dart';
export 'src/core/entities/response.dart';
export 'src/core/entities/point_route.dart';
export 'src/protocols/custom_protocol_line.dart';
export 'src/protocols/jsd_line.dart';
export 'src/api/api_handle_error.dart';
Expand Down
7 changes: 3 additions & 4 deletions lib/src/api/api_handle_error.dart
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
import 'package:hmi_core/hmi_core.dart';

Check failure on line 1 in lib/src/api/api_handle_error.dart

View workflow job for this annotation

GitHub Actions / coverage

Low coverage level

0.00% < 30%
import 'package:hmi_networking/src/core/entities/response.dart';
import 'api_params.dart';
import 'json_to.dart';

///
class ApiHandleError<T> {
static const _debug = true;
static const _log = Log('ApiHandleError');
final JsonTo<Map<String, dynamic>> _json;
ApiHandleError({
required JsonTo<Map<String, dynamic>> json,
}):
_json = json;
Future<Response<T>> fetch({required ApiParams params}) {
log(_debug, '[ApiHandleError.fetch]');
_log.debug('<$T> [ApiHandleError.fetch]');
return _json
.parse(params: params)
.then((parsedResponse) {
// final int dataCount = int.parse('${_parsed['dataCount']}');
log(_debug, '[ApiHandleError.fetch] _parsedResponse: ', parsedResponse);
_log.debug('<$T> [.fetch] parsedResponse: $parsedResponse');
if (parsedResponse.hasData) {
final sqlData = parsedResponse.data;
if (sqlData != null) {
Expand Down
12 changes: 6 additions & 6 deletions lib/src/api/api_request.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'dart:async';

Check failure on line 1 in lib/src/api/api_request.dart

View workflow job for this annotation

GitHub Actions / coverage

Low coverage level

2.94% < 30%
import 'dart:convert';
import 'dart:io';
import 'package:hmi_core/hmi_core.dart';
Expand All @@ -8,7 +8,7 @@
/// с параметрами params
/// Возвращает строку json
class ApiRequest {
static const _debug = true;
static const _log = Log('ApiRequest');
final String _url;
final String _api;
final int _port;
Expand All @@ -21,17 +21,17 @@
_api = api,
_port = port;
Future<String> fetch({required ApiParams params}) {
log(_debug, '[ApiRequest.fetch]');
_log.debug('[.fetch]');
return _fetchJsonFromUrl(_url, _port, _api, params);
}
///
Future<String> _fetchJsonFromUrl(String url, int port, String api, ApiParams params) async {
log(_debug, '[ApiRequest._fetchJsonFromUrl] ip: $url:$port$api');
_log.debug('[._fetchJsonFromUrl] ip: $url:$port$api');
return Socket
.connect(url, _port, timeout: const Duration(seconds: 5))
.then((socket) {
final jsonData = params.toJson();
log(_debug, '[ApiRequest._fetchJsonFromUrl] jsonData: ', jsonData);
_log.debug('[._fetchJsonFromUrl] jsonData: $jsonData');
socket.add(
utf8.encode(jsonData),
);
Expand All @@ -47,14 +47,14 @@
socket.close();
},
onDone: () {
log(_debug, '[ApiRequest.onDone]');
_log.debug('[.onDone]');
if (!complete.isCompleted) {
complete.complete('');
}
socket.close();
},
onError: (Object error) {
log(_debug, '[ApiRequest.onError]');
_log.debug('[.onError]');
socket.close();
return __connectionFailure(error, StackTrace.current);
},
Expand Down
10 changes: 5 additions & 5 deletions lib/src/api/json_to.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ignore_for_file: no_runtimetype_tostring

Check failure on line 1 in lib/src/api/json_to.dart

View workflow job for this annotation

GitHub Actions / coverage

Low coverage level

0.00% < 30%
import 'dart:convert';
import 'package:hmi_core/hmi_core.dart';
import 'package:hmi_networking/src/core/entities/response.dart';
Expand All @@ -6,7 +6,7 @@
import 'api_request.dart';
///
class JsonTo<T> {
static const _debug = false;
static const _log = Log('JsonTo');
final ApiRequest _request;
///
const JsonTo({
Expand All @@ -15,11 +15,11 @@
_request = request;
///
Future<Response<T>> parse({required ApiParams params}) {
log(_debug, '[$JsonTo.parse] params: ', params);
_log.debug('<$T> [.parse] params: $params');
return _request
.fetch(params: params)
.then((json) {
log(_debug, '[$JsonTo.parse] _json: ', json);
_log.debug('<$T> [.parse] json: $json');
if (json.isNotEmpty) {
try {
final T parsed = const JsonCodec().decode(json) as T;
Expand All @@ -29,7 +29,7 @@
errDump: '',
);
} catch (error) {
log(_debug, 'Ошибка в методе $runtimeType.parse() on json: "$json"\n\t$error');
_log.error('<$T> Ошибка в методе $runtimeType.parse() on json: "$json"\n\t$error');
return Response(
errCount: 1,
errDump: 'Ошибка в методе $runtimeType.parse() $error',
Expand All @@ -40,7 +40,7 @@
// );
}
} else {
log(_debug, 'Ошибка в методе $runtimeType.parse() json is empty');
_log.error('<$T> Ошибка в методе $runtimeType.parse() json is empty');
return Response(
errCount: 1,
errDump: 'Ошибка в методе $runtimeType.parse() json is empty',
Expand Down
2 changes: 1 addition & 1 deletion lib/src/auth/authenticate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'auth_result.dart';
import 'user/app_user_single.dart';
///
class Authenticate {
final _log = const Log('Authenticate')..level = LogLevel.debug;
static const _log = Log('Authenticate');
final _storeKey = 'spwd';
AppUserSingle _user;
///
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'dart:async';

Check notice on line 1 in lib/src/core/ds_client/cache/delayed/ds_client_delayed_cache.dart

View workflow job for this annotation

GitHub Actions / coverage

Good coverage level

100.00%
import 'package:hmi_core/hmi_core.dart';
import 'package:hmi_networking/src/core/ds_client/cache/ds_client_cache.dart';
import 'package:hmi_networking/src/core/ds_client/cache/file/ds_client_file_cache.dart';
Expand All @@ -7,7 +7,7 @@
///
/// Periodically persists primary cache into secondary.
final class DsClientDelayedCache implements DsClientCache {
static final _log = const Log('DsClientDelayedCache')..level = LogLevel.debug;
static const _log = Log('DsClientDelayedCache');
final DsClientCache _primaryCache;
final DsClientCache _secondaryCache;
final Duration _cachingTimeout;
Expand All @@ -33,7 +33,7 @@
_cachingTimeout = cachingTimeout;
//
@override
Future<Option<DsDataPoint>> get(String pointName) => _primaryCache.get(pointName);
Future<Option<DsDataPoint>> get(DsPointName pointName) => _primaryCache.get(pointName);
//
@override
Future<List<DsDataPoint>> getAll() => _primaryCache.getAll();
Expand Down
2 changes: 1 addition & 1 deletion lib/src/core/ds_client/cache/ds_client_cache.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import 'package:hmi_core/hmi_core.dart';
abstract interface class DsClientCache {
///
/// Retrieves point from cache by its name.
Future<Option<DsDataPoint>> get(String pointName);
Future<Option<DsDataPoint>> get(DsPointName pointName);
///
/// Retrieves all points from cache.
Future<List<DsDataPoint>> getAll();
Expand Down
8 changes: 4 additions & 4 deletions lib/src/core/ds_client/cache/file/ds_client_file_cache.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'package:hmi_core/hmi_core.dart';

Check notice on line 1 in lib/src/core/ds_client/cache/file/ds_client_file_cache.dart

View workflow job for this annotation

GitHub Actions / coverage

Good coverage level

94.73%
import 'package:hmi_networking/src/core/ds_client/cache/ds_client_cache.dart';
import 'package:hmi_networking/src/core/ds_client/cache/file/ds_cache_file.dart';

Expand All @@ -13,9 +13,9 @@
}) : _cacheFile = cacheFile;
//
@override
Future<Option<DsDataPoint>> get(String pointName) async {
Future<Option<DsDataPoint>> get(DsPointName pointName) async {
final points = await _cacheFile.read();
final point = points[pointName];
final point = points[pointName.toString()];
return switch(point) {
null => const None() as Option<DsDataPoint>,
_ => Some(point),
Expand All @@ -32,7 +32,7 @@
@override
Future<void> add(DsDataPoint point) async {
final cache = await _cacheFile.read();
cache[point.name.name] = point;
cache[point.name.toString()] = point;
return _cacheFile.write(cache);
}
//
Expand All @@ -41,7 +41,7 @@
final cache = await _cacheFile.read();
cache.addEntries(
points.map(
(point) => MapEntry(point.name.name, point),
(point) => MapEntry(point.name.toString(), point),
),
);
return _cacheFile.write(cache);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'package:hmi_core/hmi_core.dart';

Check failure on line 1 in lib/src/core/ds_client/cache/filtered/ds_client_filtered_cache.dart

View workflow job for this annotation

GitHub Actions / coverage

Low coverage level

0.00% < 30%
import 'package:hmi_networking/src/core/ds_client/cache/ds_client_cache.dart';
///
/// [DsClientCache] that checks condition before addition or (optionally) retrievement of point.
/// If that condition is false, point is not added/retrieved.
class DsClientFilteredCache implements DsClientCache {
final DsClientCache _cache;
final bool Function(DsDataPoint) _filter;
final bool _filterOnGet;
///
/// [DsClientCache] that checks condition before addition or (optionally) retrievement of point.
/// If that condition is false, point is not added/obtained.
///
/// [cache] - underlying cache to apply filtering to.
///
/// [filterOnGet] - should filtering be applied to obtain data?
const DsClientFilteredCache({
required bool Function(DsDataPoint) filter,
required DsClientCache cache,
bool filterOnGet = false,
}) :
_filter = filter,
_cache = cache,
_filterOnGet = filterOnGet;

//
@override
Future<void> add(DsDataPoint point) async {
if(_filter(point)) {
await _cache.add(point);
}
}
//
@override
Future<void> addMany(Iterable<DsDataPoint> points) {
return _cache.addMany(points.where(_filter));
}
//
@override
Future<Option<DsDataPoint>> get(DsPointName pointName) async {
final option = await _cache.get(pointName);
return switch(option) {
Some(value:final point) => switch(_filterOnGet) {
true => _filter(point)
? Some(point)
: const None() as Option<DsDataPoint>,
false => Some(point),
},
None() => const None(),
};
}
@override
Future<List<DsDataPoint>> getAll() {
return _cache.getAll()
.then((points) => switch(_filterOnGet) {
true => points.where(_filter).toList(),
false => points,
});
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import 'dart:async';

Check notice on line 1 in lib/src/core/ds_client/cache/memory/ds_client_memory_cache.dart

View workflow job for this annotation

GitHub Actions / coverage

Good coverage level

92.85%
import 'package:hmi_core/hmi_core.dart';
import 'package:hmi_networking/src/core/ds_client/cache/ds_client_cache.dart';

Expand All @@ -15,8 +15,8 @@
}
//
@override
Future<Option<DsDataPoint>> get(String pointName) async {
final point = _cache[pointName];
Future<Option<DsDataPoint>> get(DsPointName pointName) async {
final point = _cache[pointName.toString()];
return switch(point) {
null => const None() as Option<DsDataPoint>,
_ => Some(point),
Expand All @@ -28,14 +28,14 @@
//
@override
Future<void> add(DsDataPoint point) async {
_cache[point.name.name] = point;
_cache[point.name.toString()] = point;
}
//
@override
Future<void> addMany(Iterable<DsDataPoint> points) async {
_cache.addEntries(
points.map(
(point) => MapEntry(point.name.name, point),
(point) => MapEntry(point.name.toString(), point),
),
);
}
Expand Down
3 changes: 2 additions & 1 deletion lib/src/core/ds_client/ds_client.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'package:hmi_core/hmi_core.dart';
import 'package:hmi_core/hmi_core_result_new.dart';

Expand Down Expand Up @@ -31,7 +32,7 @@ abstract class DsClient {
/// в потоке Stream<DsDataPoint> stream
/// В качестве результата Result<bool> получает результат записи в socket
Future<ResultF<void>> send(
DsCommand dsCommand,
DsDataPoint point,
);
///
/// Делает запрос на S7 DataServer что бы получить все точки данных
Expand Down
11 changes: 9 additions & 2 deletions lib/src/core/ds_client/ds_client_fake.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// ignore_for_file: unused_field

Check failure on line 1 in lib/src/core/ds_client/ds_client_fake.dart

View workflow job for this annotation

GitHub Actions / coverage

Low coverage level

0.00% < 30%
import 'dart:async';
import 'dart:math';

Expand Down Expand Up @@ -26,7 +26,7 @@
///
/// Методы работающие только в режиме эмуляции для удобства тестирования
class DsClientFake implements DsClient {
static final _log = const Log('DsClientFake')..level = LogLevel.info;
static const _log = Log('DsClientFake');
final Map<String, StreamController<DsDataPoint>> _receivers = {};
final Map<String, CustomDataGenerator> _generators = {};
late StreamTransformer doubleTransformer;
Expand Down Expand Up @@ -88,7 +88,7 @@
/// В качестве результата Result<bool> получает результат записи в socket
@override
Future<ResultF<void>> send(
DsCommand dsCommand,
DsDataPoint point,
) {
throw Failure.unexpected(
message: '[$DsClientFake.send] method not implemented, used only for emulation in the test mode',
Expand Down Expand Up @@ -245,6 +245,7 @@
name: data.name,
value: int.parse('${data.value}'),
status: data.status,
cot: data.cot,
timestamp: data.timestamp,
),
);
Expand All @@ -255,6 +256,7 @@
name: data.name,
value: int.parse('${data.value}') > 0,
status: data.status,
cot: data.cot,
timestamp: data.timestamp,
),
);
Expand All @@ -265,6 +267,7 @@
name: data.name,
value: double.parse('${data.value}'),
status: data.status,
cot: data.cot,
timestamp: data.timestamp,
),
);
Expand All @@ -286,6 +289,7 @@
name: DsPointName('/'),
value: false,
status: DsStatus.ok,
cot: data.cot,
timestamp: DateTime.now().toIso8601String(),
),
);
Expand All @@ -296,6 +300,7 @@
name: DsPointName('/'),
value: true,
status: DsStatus.ok,
cot: data.cot,
timestamp: DateTime.now().toIso8601String(),
),
);
Expand All @@ -315,6 +320,7 @@
name: name, //'AnalogSensors.Winch.EncoderBR1',
value: event,
status: DsStatus.ok,
cot: DsCot.inf,
timestamp: DateTime.now().toIso8601String(),
);
if (_receivers.keys.contains(point.name.name)) {
Expand All @@ -328,6 +334,7 @@
type: DsDataType.integer,
name: name, //'AnalogSensors.Winch.EncoderBR1',
value: event,
cot: DsCot.inf,
status: DsStatus.ok,
timestamp: DateTime.now().toIso8601String(),
);
Expand Down
Loading
Loading