2019-08-31 22:10:07 +03:00
|
|
|
part of '../main.dart';
|
2019-03-26 00:18:30 +02:00
|
|
|
|
2019-08-31 22:10:07 +03:00
|
|
|
class ConnectionManager {
|
2019-03-26 00:18:30 +02:00
|
|
|
|
2019-08-31 22:10:07 +03:00
|
|
|
static final ConnectionManager _instance = ConnectionManager._internal();
|
2019-03-26 00:18:30 +02:00
|
|
|
|
2019-08-31 22:10:07 +03:00
|
|
|
factory ConnectionManager() {
|
2019-03-26 00:18:30 +02:00
|
|
|
return _instance;
|
|
|
|
}
|
|
|
|
|
2019-08-31 22:10:07 +03:00
|
|
|
ConnectionManager._internal();
|
2019-03-26 00:18:30 +02:00
|
|
|
|
|
|
|
StreamSubscription _socketSubscription;
|
|
|
|
Duration connectTimeout = Duration(seconds: 15);
|
|
|
|
|
|
|
|
bool isConnected = false;
|
2020-05-13 13:57:26 +03:00
|
|
|
bool settingsLoaded = false;
|
2019-03-26 00:18:30 +02:00
|
|
|
|
|
|
|
var onStateChangeCallback;
|
2020-03-20 01:16:59 +02:00
|
|
|
var onLovelaceUpdatedCallback;
|
2019-03-26 00:18:30 +02:00
|
|
|
|
|
|
|
IOWebSocketChannel _socket;
|
|
|
|
|
|
|
|
int _currentMessageId = 0;
|
|
|
|
Map<String, Completer> _messageResolver = {};
|
|
|
|
|
2020-05-13 13:57:26 +03:00
|
|
|
Future init({bool loadSettings, bool forceReconnect: false}) {
|
2019-03-26 00:18:30 +02:00
|
|
|
Completer completer = Completer();
|
2020-05-13 13:57:26 +03:00
|
|
|
AppSettings().load(loadSettings).then((_) {
|
2020-05-14 13:56:52 +03:00
|
|
|
Logger.d('Checking config...');
|
2020-05-13 13:57:26 +03:00
|
|
|
if (AppSettings().isNotConfigured()) {
|
2020-05-14 13:56:52 +03:00
|
|
|
Logger.d('This is first start');
|
2020-05-03 02:02:18 +03:00
|
|
|
completer.completeError(HACNotSetUpException());
|
2020-05-13 13:57:26 +03:00
|
|
|
} else if (AppSettings().isSomethingMissed()) {
|
2020-05-01 16:47:41 +03:00
|
|
|
completer.completeError(HACException.checkConnectionSettings());
|
2020-05-13 13:57:26 +03:00
|
|
|
} else if (!AppSettings().isAuthenticated) {
|
2020-05-14 23:53:01 +03:00
|
|
|
settingsLoaded = true;
|
2020-05-13 13:57:26 +03:00
|
|
|
AppSettings().startAuth().then((_) {
|
2019-06-15 14:36:11 +03:00
|
|
|
_doConnect(completer: completer, forceReconnect: forceReconnect);
|
|
|
|
}).catchError((e) {
|
|
|
|
completer.completeError(e);
|
|
|
|
});
|
|
|
|
} else {
|
2020-05-14 23:53:01 +03:00
|
|
|
settingsLoaded = true;
|
2019-04-05 11:48:41 +03:00
|
|
|
_doConnect(completer: completer, forceReconnect: forceReconnect);
|
2020-05-13 13:57:26 +03:00
|
|
|
}
|
|
|
|
});
|
2019-04-05 11:48:41 +03:00
|
|
|
|
|
|
|
return completer.future;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _doConnect({Completer completer, bool forceReconnect}) {
|
|
|
|
if (forceReconnect || !isConnected) {
|
2019-11-29 14:45:59 +02:00
|
|
|
_disconnect().then((_){
|
|
|
|
_connect().timeout(connectTimeout).then((_) {
|
|
|
|
completer?.complete();
|
|
|
|
}).catchError((e) {
|
|
|
|
_disconnect().then((_) {
|
|
|
|
if (e is TimeoutException) {
|
|
|
|
if (connecting != null && !connecting.isCompleted) {
|
2020-05-01 16:47:41 +03:00
|
|
|
connecting.completeError(HACException("Connection timeout"));
|
2019-11-29 14:45:59 +02:00
|
|
|
}
|
2020-05-01 16:47:41 +03:00
|
|
|
completer?.completeError(HACException("Connection timeout"));
|
|
|
|
} else if (e is HACException) {
|
2019-11-29 14:45:59 +02:00
|
|
|
completer?.completeError(e);
|
|
|
|
} else {
|
2020-05-01 16:47:41 +03:00
|
|
|
completer?.completeError(HACException("${e.toString()}"));
|
2019-11-29 12:58:24 +02:00
|
|
|
}
|
2019-11-29 14:45:59 +02:00
|
|
|
});
|
2019-03-29 11:04:43 +02:00
|
|
|
});
|
|
|
|
});
|
2019-04-05 11:48:41 +03:00
|
|
|
} else {
|
2019-04-19 14:07:44 +03:00
|
|
|
completer?.complete();
|
2019-03-26 00:18:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-29 11:04:43 +02:00
|
|
|
Completer connecting;
|
|
|
|
|
2019-06-16 16:32:55 +03:00
|
|
|
Future _connect() {
|
2019-03-29 11:04:43 +02:00
|
|
|
if (connecting != null && !connecting.isCompleted) {
|
2019-04-05 12:23:31 +03:00
|
|
|
Logger.w("Previous connection attempt pending...");
|
|
|
|
return connecting.future;
|
|
|
|
} else {
|
|
|
|
connecting = Completer();
|
2019-06-16 16:32:55 +03:00
|
|
|
_disconnect().then((_) {
|
2019-08-26 18:55:12 +03:00
|
|
|
Logger.d("Socket connecting...");
|
2019-11-29 13:21:45 +02:00
|
|
|
try {
|
|
|
|
_socket = IOWebSocketChannel.connect(
|
2020-05-13 13:57:26 +03:00
|
|
|
AppSettings().webSocketAPIEndpoint, pingInterval: Duration(seconds: 15));
|
2019-11-29 13:21:45 +02:00
|
|
|
_socketSubscription = _socket.stream.listen(
|
|
|
|
(message) {
|
|
|
|
isConnected = true;
|
|
|
|
var data = json.decode(message);
|
|
|
|
if (data["type"] == "auth_required") {
|
|
|
|
Logger.d("[Received] <== ${data.toString()}");
|
|
|
|
_authenticate().then((_) {
|
|
|
|
Logger.d('Authentication complete');
|
|
|
|
connecting.complete();
|
|
|
|
}).catchError((e) {
|
|
|
|
if (!connecting.isCompleted) connecting.completeError(e);
|
|
|
|
});
|
|
|
|
} else if (data["type"] == "auth_ok") {
|
2020-05-06 19:40:19 +03:00
|
|
|
String v = data["ha_version"];
|
|
|
|
if (v != null && v.isNotEmpty) {
|
2020-05-13 13:57:26 +03:00
|
|
|
AppSettings().haVersion = double.tryParse(v.replaceFirst('0.','')) ?? 0;
|
2020-05-06 19:40:19 +03:00
|
|
|
}
|
2020-05-13 13:57:26 +03:00
|
|
|
Logger.d("Home assistant version: $v (${AppSettings().haVersion})");
|
2020-05-06 19:40:19 +03:00
|
|
|
Crashlytics.instance.setString('ha_version', v);
|
2019-11-29 15:40:51 +02:00
|
|
|
Logger.d("[Connection] Subscribing to events");
|
2020-03-20 01:16:59 +02:00
|
|
|
sendSocketMessage(
|
|
|
|
type: "subscribe_events",
|
|
|
|
additionalData: {"event_type": "lovelace_updated"},
|
|
|
|
);
|
2019-11-29 15:40:51 +02:00
|
|
|
sendSocketMessage(
|
|
|
|
type: "subscribe_events",
|
|
|
|
additionalData: {"event_type": "state_changed"},
|
|
|
|
).whenComplete((){
|
|
|
|
_messageResolver["auth"]?.complete();
|
|
|
|
_messageResolver.remove("auth");
|
2020-05-13 13:57:26 +03:00
|
|
|
if (AppSettings().isAuthenticated) {
|
2019-11-29 15:40:51 +02:00
|
|
|
if (!connecting.isCompleted) connecting.complete();
|
|
|
|
}
|
|
|
|
});
|
2019-11-29 13:21:45 +02:00
|
|
|
} else if (data["type"] == "auth_invalid") {
|
|
|
|
Logger.d("[Received] <== ${data.toString()}");
|
2020-05-01 16:47:41 +03:00
|
|
|
_messageResolver["auth"]?.completeError(HACException("${data["message"]}", actions: [HAErrorAction.loginAgain()]));
|
2019-11-29 13:21:45 +02:00
|
|
|
_messageResolver.remove("auth");
|
2020-05-01 16:47:41 +03:00
|
|
|
if (!connecting.isCompleted) connecting.completeError(HACException("${data["message"]}", actions: [HAErrorAction.tryAgain(title: "Retry"), HAErrorAction.loginAgain(title: "Relogin")]));
|
2019-11-29 13:21:45 +02:00
|
|
|
} else {
|
|
|
|
_handleMessage(data);
|
2019-06-16 16:32:55 +03:00
|
|
|
}
|
2019-11-29 13:21:45 +02:00
|
|
|
},
|
|
|
|
cancelOnError: true,
|
|
|
|
onDone: () => _handleSocketClose(connecting),
|
|
|
|
onError: (e) => _handleSocketError(e, connecting)
|
|
|
|
);
|
|
|
|
} catch(exeption) {
|
2020-05-01 16:47:41 +03:00
|
|
|
connecting.completeError(HACException("${exeption.toString()}"));
|
2019-11-29 13:21:45 +02:00
|
|
|
}
|
2019-06-16 16:32:55 +03:00
|
|
|
});
|
2019-03-29 11:04:43 +02:00
|
|
|
return connecting.future;
|
|
|
|
}
|
2019-03-26 00:18:30 +02:00
|
|
|
}
|
|
|
|
|
2019-04-19 14:07:44 +03:00
|
|
|
Future _disconnect() {
|
|
|
|
Completer completer = Completer();
|
|
|
|
if (!isConnected) {
|
|
|
|
completer.complete();
|
|
|
|
} else {
|
|
|
|
isConnected = false;
|
|
|
|
List<Future> fl = [];
|
|
|
|
Logger.d("Socket disconnecting...");
|
|
|
|
if (_socketSubscription != null) {
|
|
|
|
fl.add(_socketSubscription.cancel());
|
|
|
|
}
|
|
|
|
if (_socket != null && _socket.sink != null &&
|
|
|
|
_socket.closeCode == null) {
|
|
|
|
fl.add(_socket.sink.close().timeout(Duration(seconds: 3)));
|
|
|
|
}
|
|
|
|
Future.wait(fl).whenComplete(() => completer.complete());
|
2019-03-30 00:29:52 +02:00
|
|
|
}
|
2019-04-19 14:07:44 +03:00
|
|
|
return completer.future;
|
2019-03-26 00:18:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
_handleMessage(data) {
|
|
|
|
if (data["type"] == "result") {
|
|
|
|
if (data["id"] != null && data["success"]) {
|
2019-09-15 18:38:02 +03:00
|
|
|
//Logger.d("[Received] <== Request id ${data['id']} was successful");
|
2019-03-26 00:18:30 +02:00
|
|
|
_messageResolver["${data["id"]}"]?.complete(data["result"]);
|
|
|
|
} else if (data["id"] != null) {
|
2020-05-01 19:24:13 +03:00
|
|
|
Logger.e("[Received] <== Error received on request id ${data['id']}: ${data['error']}", skipCrashlytics: true);
|
2020-05-01 16:47:41 +03:00
|
|
|
_messageResolver["${data["id"]}"]?.completeError("${data["error"]["code"]}: ${data["error"]["message"]}");
|
2019-03-26 00:18:30 +02:00
|
|
|
}
|
|
|
|
_messageResolver.remove("${data["id"]}");
|
|
|
|
} else if (data["type"] == "event") {
|
2020-03-20 01:16:59 +02:00
|
|
|
if (data["event"] != null) {
|
|
|
|
if (data["event"]["event_type"] == "state_changed") {
|
|
|
|
Logger.d("[Received] <== ${data['type']}.${data["event"]["event_type"]}: ${data["event"]["data"]["entity_id"]}");
|
|
|
|
onStateChangeCallback(data["event"]["data"]);
|
|
|
|
} else if (data["event"]["event_type"] == "lovelace_updated") {
|
|
|
|
Logger.d("[Received] <== ${data['type']}.${data["event"]["event_type"]}: $data");
|
|
|
|
onLovelaceUpdatedCallback();
|
|
|
|
}
|
|
|
|
}
|
2019-03-26 00:18:30 +02:00
|
|
|
} else {
|
|
|
|
Logger.d("[Received unhandled] <== ${data.toString()}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void _handleSocketClose(Completer connectionCompleter) {
|
|
|
|
Logger.d("Socket disconnected.");
|
2019-11-29 13:21:45 +02:00
|
|
|
_disconnect().then((_) {
|
|
|
|
if (!connectionCompleter.isCompleted) {
|
|
|
|
isConnected = false;
|
2020-05-01 16:47:41 +03:00
|
|
|
connectionCompleter.completeError(HACException("Disconnected", actions: [HAErrorAction.reconnect()]));
|
2019-11-29 13:21:45 +02:00
|
|
|
}
|
2020-05-01 16:47:41 +03:00
|
|
|
eventBus.fire(ShowErrorEvent(HACException("Unable to connect to Home Assistant")));
|
2019-11-29 13:21:45 +02:00
|
|
|
});
|
2019-03-26 00:18:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void _handleSocketError(e, Completer connectionCompleter) {
|
2020-05-01 19:24:13 +03:00
|
|
|
Logger.e("Socket stream Error: $e", skipCrashlytics: true);
|
2019-11-29 13:21:45 +02:00
|
|
|
_disconnect().then((_) {
|
|
|
|
if (!connectionCompleter.isCompleted) {
|
|
|
|
isConnected = false;
|
2020-05-01 16:47:41 +03:00
|
|
|
connectionCompleter.completeError(HACException("Disconnected", actions: [HAErrorAction.reconnect()]));
|
2019-11-29 13:21:45 +02:00
|
|
|
}
|
2020-05-01 16:47:41 +03:00
|
|
|
eventBus.fire(ShowErrorEvent(HACException("Unable to connect to Home Assistant")));
|
2019-11-29 13:21:45 +02:00
|
|
|
});
|
2019-03-26 00:18:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Future _authenticate() {
|
|
|
|
Completer completer = Completer();
|
2020-05-13 13:57:26 +03:00
|
|
|
if (AppSettings().isAuthenticated) {
|
2019-03-26 00:18:30 +02:00
|
|
|
Logger.d( "Long-lived token exist");
|
|
|
|
Logger.d( "[Sending] ==> auth request");
|
|
|
|
sendSocketMessage(
|
|
|
|
type: "auth",
|
2020-05-13 15:46:25 +03:00
|
|
|
additionalData: {"access_token": "${AppSettings().longLivedToken}"},
|
2019-03-26 00:18:30 +02:00
|
|
|
auth: true
|
|
|
|
).then((_) {
|
|
|
|
completer.complete();
|
|
|
|
}).catchError((e) => completer.completeError(e));
|
2020-05-13 15:46:25 +03:00
|
|
|
} else if (AppSettings().isTempAuthenticated != null) {
|
2019-03-26 00:18:30 +02:00
|
|
|
Logger.d("We have temp token. Loging in...");
|
|
|
|
sendSocketMessage(
|
|
|
|
type: "auth",
|
2020-05-13 15:46:25 +03:00
|
|
|
additionalData: {"access_token": "${AppSettings().tempToken}"},
|
2019-03-26 00:18:30 +02:00
|
|
|
auth: true
|
|
|
|
).then((_) {
|
|
|
|
Logger.d("Requesting long-lived token...");
|
|
|
|
_getLongLivedToken().then((_) {
|
2019-06-16 16:32:55 +03:00
|
|
|
Logger.d("getLongLivedToken finished");
|
2019-03-26 00:18:30 +02:00
|
|
|
completer.complete();
|
|
|
|
}).catchError((e) {
|
|
|
|
Logger.e("Can't get long-lived token: $e");
|
|
|
|
throw e;
|
|
|
|
});
|
|
|
|
}).catchError((e) => completer.completeError(e));
|
|
|
|
} else {
|
2020-05-01 16:47:41 +03:00
|
|
|
completer.completeError(HACException("General login error"));
|
2019-03-26 00:18:30 +02:00
|
|
|
}
|
|
|
|
return completer.future;
|
|
|
|
}
|
|
|
|
|
2020-05-13 15:46:25 +03:00
|
|
|
Future logout() async {
|
2019-09-04 23:40:37 +03:00
|
|
|
Logger.d("Logging out");
|
2020-05-13 15:46:25 +03:00
|
|
|
await _disconnect();
|
|
|
|
await AppSettings().clearTokens();
|
2019-03-26 00:18:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Future _getLongLivedToken() {
|
|
|
|
Completer completer = Completer();
|
|
|
|
sendSocketMessage(type: "auth/long_lived_access_token", additionalData: {"client_name": "HA Client app ${DateTime.now().millisecondsSinceEpoch}", "lifespan": 365}).then((data) {
|
|
|
|
Logger.d("Got long-lived token.");
|
2020-05-13 15:46:25 +03:00
|
|
|
AppSettings().saveLongLivedToken(data);
|
2020-05-29 21:26:20 +03:00
|
|
|
completer.complete();
|
2019-03-26 00:18:30 +02:00
|
|
|
}).catchError((e) {
|
2020-05-01 16:47:41 +03:00
|
|
|
completer.completeError(HACException("Authentication error: $e", actions: [HAErrorAction.reload(title: "Retry"), HAErrorAction.loginAgain(title: "Relogin")]));
|
2019-03-26 00:18:30 +02:00
|
|
|
});
|
|
|
|
return completer.future;
|
|
|
|
}
|
|
|
|
|
|
|
|
Future sendSocketMessage({String type, Map additionalData, bool auth: false}) {
|
|
|
|
Completer _completer = Completer();
|
|
|
|
Map dataObject = {"type": "$type"};
|
|
|
|
String callbackName;
|
|
|
|
if (!auth) {
|
|
|
|
_incrementMessageId();
|
|
|
|
dataObject["id"] = _currentMessageId;
|
|
|
|
callbackName = "$_currentMessageId";
|
|
|
|
} else {
|
|
|
|
callbackName = "auth";
|
|
|
|
}
|
|
|
|
if (additionalData != null) {
|
|
|
|
dataObject.addAll(additionalData);
|
|
|
|
}
|
|
|
|
_messageResolver[callbackName] = _completer;
|
|
|
|
String rawMessage = json.encode(dataObject);
|
2019-03-29 11:04:43 +02:00
|
|
|
if (!isConnected) {
|
2019-11-29 13:24:29 +02:00
|
|
|
_connect().timeout(connectTimeout).then((_) {
|
2019-08-26 18:55:12 +03:00
|
|
|
Logger.d("[Sending] ==> ${auth ? "type="+dataObject['type'] : rawMessage}");
|
2019-03-29 11:04:43 +02:00
|
|
|
_socket.sink.add(rawMessage);
|
|
|
|
}).catchError((e) {
|
2019-11-28 20:33:27 +02:00
|
|
|
if (!_completer.isCompleted) {
|
2020-05-01 16:47:41 +03:00
|
|
|
_completer.completeError(HACException("No connection to Home Assistant", actions: [HAErrorAction.reconnect()]));
|
2019-11-28 20:33:27 +02:00
|
|
|
}
|
2019-03-29 11:04:43 +02:00
|
|
|
});
|
|
|
|
} else {
|
2019-08-26 18:55:12 +03:00
|
|
|
Logger.d("[Sending] ==> ${auth ? "type="+dataObject['type'] : rawMessage}");
|
2019-03-29 11:04:43 +02:00
|
|
|
_socket.sink.add(rawMessage);
|
|
|
|
}
|
2019-03-26 00:18:30 +02:00
|
|
|
return _completer.future;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _incrementMessageId() {
|
|
|
|
_currentMessageId += 1;
|
|
|
|
}
|
|
|
|
|
2020-02-19 12:17:08 +02:00
|
|
|
Future callService({@required String domain, @required String service, entityId, Map data}) {
|
2019-10-28 19:59:47 +02:00
|
|
|
eventBus.fire(NotifyServiceCallEvent(domain, service, entityId));
|
2019-11-08 21:37:41 +02:00
|
|
|
Logger.d("Service call: $domain.$service, $entityId, $data");
|
2019-09-15 17:29:49 +03:00
|
|
|
Completer completer = Completer();
|
2019-03-26 00:18:30 +02:00
|
|
|
Map serviceData = {};
|
|
|
|
if (entityId != null) {
|
|
|
|
serviceData["entity_id"] = entityId;
|
|
|
|
}
|
2019-11-08 21:37:41 +02:00
|
|
|
if (data != null && data.isNotEmpty) {
|
|
|
|
serviceData.addAll(data);
|
2019-03-26 00:18:30 +02:00
|
|
|
}
|
|
|
|
if (serviceData.isNotEmpty)
|
2019-09-15 17:29:49 +03:00
|
|
|
sendHTTPPost(
|
2019-09-14 20:08:10 +03:00
|
|
|
endPoint: "/api/services/$domain/$service",
|
|
|
|
data: json.encode(serviceData)
|
2020-05-01 16:47:41 +03:00
|
|
|
).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HACException(e.toString())));
|
2019-09-14 20:08:10 +03:00
|
|
|
//return sendSocketMessage(type: "call_service", additionalData: {"domain": domain, "service": service, "service_data": serviceData});
|
2019-03-26 00:18:30 +02:00
|
|
|
else
|
2019-09-15 17:29:49 +03:00
|
|
|
sendHTTPPost(
|
2019-09-14 20:08:10 +03:00
|
|
|
endPoint: "/api/services/$domain/$service"
|
2020-05-01 16:47:41 +03:00
|
|
|
).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HACException(e.toString())));
|
2019-09-14 20:08:10 +03:00
|
|
|
//return sendSocketMessage(type: "call_service", additionalData: {"domain": domain, "service": service});
|
2019-09-15 17:29:49 +03:00
|
|
|
return completer.future;
|
2019-03-26 00:18:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Future<List> getHistory(String entityId) async {
|
|
|
|
DateTime now = DateTime.now();
|
|
|
|
//String endTime = formatDate(now, [yyyy, '-', mm, '-', dd, 'T', HH, ':', nn, ':', ss, z]);
|
|
|
|
String startTime = formatDate(now.subtract(Duration(hours: 24)), [yyyy, '-', mm, '-', dd, 'T', HH, ':', nn, ':', ss, z]);
|
2020-05-13 15:46:25 +03:00
|
|
|
String url = "${AppSettings().httpWebHost}/api/history/period/$startTime?&filter_entity_id=$entityId";
|
2019-08-26 18:55:12 +03:00
|
|
|
Logger.d("[Sending] ==> HTTP /api/history/period/$startTime?&filter_entity_id=$entityId");
|
2019-03-26 00:18:30 +02:00
|
|
|
http.Response historyResponse;
|
|
|
|
historyResponse = await http.get(url, headers: {
|
2020-05-13 15:46:25 +03:00
|
|
|
"authorization": "Bearer ${AppSettings().longLivedToken}",
|
2019-03-26 00:18:30 +02:00
|
|
|
"Content-Type": "application/json"
|
|
|
|
});
|
|
|
|
var history = json.decode(historyResponse.body);
|
|
|
|
if (history is List) {
|
2019-08-26 18:55:12 +03:00
|
|
|
Logger.d( "[Received] <== HTTP ${history.first.length} history recors");
|
2019-03-26 00:18:30 +02:00
|
|
|
return history;
|
|
|
|
} else {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-29 13:09:34 +02:00
|
|
|
Future sendHTTPPost({String endPoint, String data, String contentType: "application/json", bool includeAuthHeader: true}) async {
|
2019-03-26 00:18:30 +02:00
|
|
|
Completer completer = Completer();
|
2020-05-13 15:46:25 +03:00
|
|
|
String url = "${AppSettings().httpWebHost}$endPoint";
|
2019-08-26 18:55:12 +03:00
|
|
|
Logger.d("[Sending] ==> HTTP $endPoint");
|
2019-03-26 00:18:30 +02:00
|
|
|
Map<String, String> headers = {};
|
|
|
|
if (contentType != null) {
|
|
|
|
headers["Content-Type"] = contentType;
|
|
|
|
}
|
|
|
|
if (includeAuthHeader) {
|
2020-05-13 15:46:25 +03:00
|
|
|
headers["authorization"] = "Bearer ${AppSettings().longLivedToken}";
|
2019-03-26 00:18:30 +02:00
|
|
|
}
|
|
|
|
http.post(
|
|
|
|
url,
|
|
|
|
headers: headers,
|
|
|
|
body: data
|
|
|
|
).then((response) {
|
2019-06-15 18:07:11 +03:00
|
|
|
if (response.statusCode >= 200 && response.statusCode < 300 ) {
|
2019-10-30 17:04:23 +02:00
|
|
|
Logger.d("[Received] <== HTTP ${response.statusCode}");
|
2019-03-26 00:18:30 +02:00
|
|
|
completer.complete(response.body);
|
|
|
|
} else {
|
2019-10-30 17:04:23 +02:00
|
|
|
Logger.d("[Received] <== HTTP ${response.statusCode}: ${response.body}");
|
2019-11-28 21:14:50 +02:00
|
|
|
completer.completeError(response);
|
2019-03-26 00:18:30 +02:00
|
|
|
}
|
|
|
|
}).catchError((e) {
|
|
|
|
completer.completeError(e);
|
|
|
|
});
|
|
|
|
return completer.future;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|