Created
September 21, 2021 21:19
-
-
Save LenniCodes/b5b44bfc92157e62536bc9d418aeca76 to your computer and use it in GitHub Desktop.
Http Core
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:convert'; | |
import 'package:http/http.dart' as http; | |
import 'package:spectrumhome/utils/system.dart'; | |
import 'package:spectrumhome/utils/notification_manager.dart' as manager; | |
const String defaultIP = "localhost:8181"; | |
String _ip = defaultIP; | |
const int requestDelay = 10; | |
const int threadTime = 3; | |
ConnectionState apiState = ConnectionState.PENDING; | |
enum ConnectionState { CONNECTED, PENDING, DISCONNECTED } | |
class APIConnectionEvent extends Event { | |
final ConnectionState state; | |
APIConnectionEvent(this.state); | |
} | |
void _setConnectionState(ConnectionState state) { | |
if (apiState == state) return; | |
apiState = state; | |
call(APIConnectionEvent(state)); | |
} | |
class ApiIPChangedEvent extends Event { | |
final String ip; | |
ApiIPChangedEvent(this.ip); | |
} | |
Map services = { | |
"connectionInfo": "api/connection/info", | |
"connectionScan": "api/connection/scan", | |
"user": "api/user", | |
"device": "api/device", | |
"type": "api/type" | |
}; | |
void changeIP(String ipChanged) { | |
_ip = ipChanged; | |
stopAPITasks(); | |
_setConnectionState(ConnectionState.PENDING); | |
call(ApiIPChangedEvent(ipChanged)); | |
} | |
void setIPRaw(String ipChanged) { | |
_ip = ipChanged; | |
} | |
String ip() { | |
return _ip; | |
} | |
int taskTime = 0; | |
int taskIterations = 0; | |
String? currentTask; | |
bool cancelTask = false; | |
Map<String, bool> taskWorker = {}; | |
List<APITaskController> controllers = []; | |
void _clearTask() { | |
if (currentTask == null) return; | |
taskIterations = 0; | |
taskTime = 0; | |
taskWorker.remove(currentTask); | |
List<APITaskController> toDelete = []; | |
controllers.forEach((element) { | |
if (element.key == currentTask) toDelete.add(element); | |
}); | |
controllers.removeWhere((element) => toDelete.contains(element)); | |
currentTask = null; | |
} | |
void stopAPIOfGroup({required String group}) { | |
print("Stopping API-Group \"$group\"..."); | |
controllers.forEach((element) { | |
if (element.group != null && element.group == group) element.stop(); | |
}); | |
} | |
void stopAPITasks() { | |
taskWorker.forEach((key, value) => taskWorker[key] = false); | |
} | |
void stopCurrentAPITask() { | |
cancelTask = true; | |
} | |
void stopAPITask({String? key, String? service, String? method}) { | |
String? keyword = key != null | |
? key | |
: (service != null && method != null | |
? buildAPITaskID(services[service], method) | |
: null); | |
if (keyword == null) return; | |
if (taskWorker.containsKey(keyword)) taskWorker[keyword] = false; | |
} | |
List<String> doneTasks = []; | |
Future<Response> request(String service, String method, Map body, | |
{String? token, | |
int? timeout, | |
String? keyword, | |
APITaskController? controller}) async { | |
String beginIP = _ip; | |
String apiPath = services[service]; | |
String key = keyword != null ? keyword : buildAPITaskID(apiPath, method); | |
if (doneTasks.contains(key)) { | |
doneTasks.remove(key); | |
} | |
if (controller != null) { | |
controller.key = key; | |
controllers.add(controller); | |
} | |
taskWorker[key] = true; | |
print("Facing \"$key\" now..."); | |
if (currentTask != null && currentTask != key) { | |
while (currentTask != null) { | |
if (!taskWorker.containsKey(key) || !taskWorker[key]!) { | |
print(" - Removing \"$key\" from Queue..."); | |
if (controller != null) controllers.remove(controller); | |
return Response(code: 408, message: "Cancelled"); | |
} | |
await Future.delayed(Duration(seconds: threadTime)); | |
} | |
} | |
if (apiState == ConnectionState.DISCONNECTED) | |
_setConnectionState(ConnectionState.PENDING); | |
currentTask = key; | |
taskTime = DateTime.now().millisecondsSinceEpoch; | |
taskIterations += 1; | |
try { | |
var response = await http.post(Uri.parse("http://" + _ip + "/" + apiPath), | |
body: jsonEncode({"method": method, "params": body}), | |
headers: { | |
"SPECTRUM-AUTH": token != null ? token : sessionToken ?? "" | |
}).timeout(Duration(seconds: 10)); | |
var result = jsonDecode(response.body); | |
if (beginIP != _ip) throw Exception(); | |
_clearTask(); | |
_setConnectionState(ConnectionState.CONNECTED); | |
if (response.statusCode != 200 && result.containsKey("error")) { | |
manager.addToQueue(text: result["error"]); | |
return Response(code: response.statusCode, message: result["error"]); | |
} else { | |
if (!doneTasks.contains(key)) { | |
doneTasks.add(key); | |
return Response(obj: result, code: 200); | |
} else | |
return Response(code: 408, message: "Internal error."); | |
} | |
} catch (exception) { | |
_setConnectionState(ConnectionState.DISCONNECTED); | |
manager.addToQueue(text: "Keine Internetverbindung."); | |
print("Error connecting to API: " + exception.toString()); | |
if (beginIP != _ip) cancelTask = true; | |
if (timeout != null && taskIterations >= timeout) cancelTask = true; | |
if (!taskWorker.containsKey(key) || !taskWorker[key]!) cancelTask = true; | |
if (cancelTask) { | |
print(" - Cancelling current running Task \"$currentTask\"..."); | |
_clearTask(); | |
manager.addToQueue(text: "Versuche es später noch einmal."); | |
cancelTask = false; | |
return Response(code: 408, message: "Timed Out"); | |
} | |
while (DateTime.now().millisecondsSinceEpoch - taskTime < | |
(requestDelay * 1000)) { | |
await Future.delayed(Duration(seconds: threadTime)); | |
} | |
if (currentTask != null && !doneTasks.contains(key)) { | |
print("trying \"$currentTask\" again..."); | |
return await request(service, method, body); | |
} | |
return Response(code: 408, message: "Internal error."); | |
} | |
} | |
class APITaskController { | |
String? key; | |
String? group; | |
APITaskController({this.group}); | |
void stop() { | |
stopAPITask(key: key); | |
} | |
} | |
String buildAPITaskID(String apiPath, String method) { | |
return apiPath + method; | |
} | |
class Response { | |
String message; | |
int code; | |
dynamic obj; | |
bool success = false; | |
bool invalidRequest = false; | |
Response( | |
{this.message = "Success.", | |
this.obj, | |
this.code = 400, | |
this.invalidRequest = false}) { | |
success = obj != null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment