Included logging

android_attempt
Felix Bruns 10 months ago
parent 427fc60e9c
commit ba90b9ca63

@ -0,0 +1,27 @@
import 'dart:io';
import 'package:logger/logger.dart';
class Log {
static final Log _instance = Log._internal();
static Logger _logger = Logger();
factory Log() {
_logger = Logger(
output: MultiOutput([
ConsoleOutput(),
FileOutput(file: File("/var/log/proxmox-dash/proxmox-dash.log")),
]),
level: Level.info,
);
return _instance;
}
void debug(m) => _logger.d(m);
void info(m) => _logger.i(m);
void warn(m) => _logger.w(m);
void error(m) => _logger.e(m);
Log._internal();
}

@ -1,20 +1,15 @@
import 'package:flutter/material.dart';
import 'package:pi_dashboard/logger.dart';
import 'src/app.dart';
import 'src/settings/settings_controller.dart';
import 'src/settings/settings_service.dart';
void main() async {
// Set up the SettingsController, which will glue user settings to multiple
// Flutter Widgets.
final settingsController = SettingsController(SettingsService());
// Load the user's preferred theme while the splash screen is displayed.
// This prevents a sudden theme change when the app is first displayed.
await settingsController.loadSettings();
// Run the app and pass in the SettingsController. The app listens to the
// SettingsController for changes, then passes it further down to the
// SettingsView.
Log().info("Application started");
runApp(MyApp(settingsController: settingsController));
Log().info("Application stopped");
}

@ -15,33 +15,19 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Glue the SettingsController to the MaterialApp.
//
// The ListenableBuilder Widget listens to the SettingsController for changes.
// Whenever the user updates their settings, the MaterialApp is rebuilt.
return ListenableBuilder(
listenable: settingsController,
builder: (BuildContext context, Widget? child) {
return MaterialApp(
// Providing a restorationScopeId allows the Navigator built by the
// MaterialApp to restore the navigation stack when a user leaves and
// returns to the app after it has been killed while running in the
// background.
restorationScopeId: 'app',
supportedLocales: const [
Locale('en', ''), // English, no country code
],
// Define a light and dark color theme. Then, read the user's
// preferred ThemeMode (light, dark, or system default) from the
// SettingsController to display the correct theme.
theme: ThemeData(),
darkTheme: ThemeData.dark(),
themeMode: settingsController.themeMode,
// Define a function to handle named routes in order to support
// Flutter web url navigation and deep linking.
onGenerateRoute: (RouteSettings routeSettings) {
return MaterialPageRoute<void>(
settings: routeSettings,

@ -1,6 +1,7 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:pi_dashboard/logger.dart';
import 'package:pi_dashboard/src/proxmox_webservice/model.dart';
import 'package:pi_dashboard/src/proxmox_webservice/service.dart';
import 'package:pi_dashboard/src/screen_helper.dart';
@ -51,11 +52,13 @@ class _ProxmoxListerState extends State<ProxmoxListerView> {
if (!success) {
return Future.error(Exception("couldn't authenticate against Proxmox"));
}
Log().info("Server auth successful");
ProxmoxNodeMap map = {};
final nodes = await _service.listNodes();
for (final node in nodes) {
map[node] = await _service.listVms(node.node);
Log().debug("received node [${node.node}] with ${map[node]?.length} vms");
}
return map;
}
@ -77,6 +80,7 @@ class _ProxmoxListerState extends State<ProxmoxListerView> {
timeout: const Duration(seconds: 60),
onExpire: () async {
await turnOffScreen();
Log().info("No input for 60 seconds. Screen turned off");
},
child: Stack(
children: [

@ -1,6 +1,7 @@
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;
import 'package:pi_dashboard/logger.dart';
import 'model.dart';
class ProxmoxWebService {
@ -40,6 +41,8 @@ class ProxmoxWebService {
_authenticated = true;
} else {
_authenticated = false;
Log().info(
"Authentication returned error code ${resp.statusCode}: ${resp.body}");
}
return _authenticated;
@ -57,7 +60,10 @@ class ProxmoxWebService {
"Cookie": "PVEAuthCookie=$_ticket"
});
if (resp.statusCode != 200) return null;
if (resp.statusCode != 200) {
Log().info("Get returned error code ${resp.statusCode}: ${resp.body}");
return null;
}
return convert.jsonDecode(resp.body) as Map<String, dynamic>;
}
@ -79,12 +85,16 @@ class ProxmoxWebService {
body: payload,
);
if (resp.statusCode != 200) return null;
if (resp.statusCode != 200) {
Log().info("Post returned error code ${resp.statusCode}: ${resp.body}");
return null;
}
return convert.jsonDecode(resp.body) as Map<String, dynamic>;
}
Future<List<ProxmoxNode>> listNodes() async {
Log().debug("Querying nodes");
List<ProxmoxNode> nodes = [];
final resp = await _doGet("/api2/json/nodes");
@ -98,6 +108,7 @@ class ProxmoxWebService {
}
Future<List<ProxmoxVm>> listVms(String node) async {
Log().debug("Querying vms");
List<ProxmoxVm> vms = [];
final resp = await _doGet("/api2/json/nodes/$node/qemu");
if (resp == null) return [];
@ -113,8 +124,11 @@ class ProxmoxWebService {
Future<bool> toggleVm(ProxmoxNode node, ProxmoxVm vm) async {
if (!_authenticated) return false;
final isRunning = vm.status == "running";
Log().info("toggling VM: ${isRunning ? "stopping" : "starting"}");
final endpoint =
"/api2/json/nodes/${node.node}/qemu/${vm.vmid}/status/${vm.status == "running" ? "stop" : "start"}";
"/api2/json/nodes/${node.node}/qemu/${vm.vmid}/status/${isRunning ? "stop" : "start"}";
final resp = await _doPost(endpoint, {}, debug: true);
if (resp == null) return false;

@ -1,6 +1,7 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:async/async.dart';
import 'package:pi_dashboard/logger.dart';
const _off = "1";
const _on = "0";
@ -8,6 +9,7 @@ const _on = "0";
bool _screenStatus = true;
Future<void> toggleScreen() async {
Log().info("Manually toggling screen light");
if (_screenStatus) {
turnOffScreen();
} else {
@ -43,6 +45,7 @@ Widget screenActivator() {
child: Material(
color: Colors.black,
child: InkWell(onTap: () async {
Log().info("Touch received: turning screen back on");
await turnOncreen();
}),
),

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:pi_dashboard/logger.dart';
import 'settings_service.dart';
@ -38,14 +39,17 @@ class SettingsController with ChangeNotifier {
Future<void> setHostname(String newHostname) async {
_hostname = newHostname;
await _setKey("hostname", hostname);
Log().debug("Hostname update: $hostname");
}
Future<void> setUsername(String newUsername) async {
_username = newUsername;
await _setKey("username", username);
Log().debug("username update: $username");
}
Future<void> setPassword(String newPassword) async {
_password = newPassword;
await _setKey("password", password);
Log().debug("password update");
}
/// Update and persist the ThemeMode based on the user's selection.
Future<void> updateThemeMode(ThemeMode? newThemeMode) async {

@ -7,13 +7,13 @@ import 'settings_controller.dart';
/// When a user changes a setting, the SettingsController is updated and
/// Widgets that listen to the SettingsController are rebuilt.
class SettingsView extends StatelessWidget {
const SettingsView({super.key, required this.controller});
const SettingsView({super.key, required this.controller});
static const routeName = '/settings';
static const routeName = '/settings';
final SettingsController controller;
final SettingsController controller;
@override
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
@ -70,8 +70,7 @@ final SettingsController controller;
onChanged: controller.setPassword,
),
],
)
),
),
);
}

@ -17,6 +17,7 @@ dependencies:
http: ^1.2.1
shared_preferences:
async: ^2.11.0
logger: ^2.2.0
flutter_gen: any
dev_dependencies:

Loading…
Cancel
Save