Skip to content

Commit

Permalink
Merge pull request #55 from a-givertzman/DsClient-startup-requests
Browse files Browse the repository at this point in the history
Implemented JDS protocol startup requests and basic communication
  • Loading branch information
Minyewoo authored Apr 22, 2024
2 parents 5960e9b + 93687b9 commit ee043b4
Show file tree
Hide file tree
Showing 58 changed files with 1,546 additions and 562 deletions.
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
Expand Up @@ -5,19 +5,18 @@ 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
Expand Up @@ -8,7 +8,7 @@ import 'api_params.dart';
/// с параметрами 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 @@ class ApiRequest {
_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 @@ class ApiRequest {
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
Expand Up @@ -6,7 +6,7 @@ import 'api_params.dart';
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 @@ class JsonTo<T> {
_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 @@ class JsonTo<T> {
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 @@ class JsonTo<T> {
// );
}
} 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
Expand Up @@ -7,7 +7,7 @@ import 'package:hmi_networking/src/core/ds_client/cache/memory/ds_client_memory_
///
/// 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 @@ final class DsClientDelayedCache implements DsClientCache {
_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
Expand Up @@ -13,9 +13,9 @@ final class DsClientFileCache implements DsClientCache {
}) : _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 @@ final class DsClientFileCache implements DsClientCache {
@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 class DsClientFileCache implements DsClientCache {
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';
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
Expand Up @@ -15,8 +15,8 @@ final class DsClientMemoryCache implements DsClientCache {
}
//
@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 @@ final class DsClientMemoryCache implements DsClientCache {
//
@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
Expand Up @@ -26,7 +26,7 @@ class EmulationParams {
///
/// Методы работающие только в режиме эмуляции для удобства тестирования
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 @@ class DsClientFake implements DsClient {
/// В качестве результата 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 @@ class DsClientFake implements DsClient {
name: data.name,
value: int.parse('${data.value}'),
status: data.status,
cot: data.cot,
timestamp: data.timestamp,
),
);
Expand All @@ -255,6 +256,7 @@ class DsClientFake implements DsClient {
name: data.name,
value: int.parse('${data.value}') > 0,
status: data.status,
cot: data.cot,
timestamp: data.timestamp,
),
);
Expand All @@ -265,6 +267,7 @@ class DsClientFake implements DsClient {
name: data.name,
value: double.parse('${data.value}'),
status: data.status,
cot: data.cot,
timestamp: data.timestamp,
),
);
Expand All @@ -286,6 +289,7 @@ class DsClientFake implements DsClient {
name: DsPointName('/'),
value: false,
status: DsStatus.ok,
cot: data.cot,
timestamp: DateTime.now().toIso8601String(),
),
);
Expand All @@ -296,6 +300,7 @@ class DsClientFake implements DsClient {
name: DsPointName('/'),
value: true,
status: DsStatus.ok,
cot: data.cot,
timestamp: DateTime.now().toIso8601String(),
),
);
Expand All @@ -315,6 +320,7 @@ class DsClientFake implements DsClient {
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 @@ class DsClientFake implements DsClient {
type: DsDataType.integer,
name: name, //'AnalogSensors.Winch.EncoderBR1',
value: event,
cot: DsCot.inf,
status: DsStatus.ok,
timestamp: DateTime.now().toIso8601String(),
);
Expand Down
Loading

0 comments on commit ee043b4

Please sign in to comment.