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:flutter/material.dart';
import 'package:pi_dashboard/logger.dart';
import 'src/app.dart'; import 'src/app.dart';
import 'src/settings/settings_controller.dart'; import 'src/settings/settings_controller.dart';
import 'src/settings/settings_service.dart'; import 'src/settings/settings_service.dart';
void main() async { void main() async {
// Set up the SettingsController, which will glue user settings to multiple
// Flutter Widgets.
final settingsController = SettingsController(SettingsService()); 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(); await settingsController.loadSettings();
// Run the app and pass in the SettingsController. The app listens to the Log().info("Application started");
// SettingsController for changes, then passes it further down to the
// SettingsView.
runApp(MyApp(settingsController: settingsController)); runApp(MyApp(settingsController: settingsController));
Log().info("Application stopped");
} }

@ -15,33 +15,19 @@ class MyApp extends StatelessWidget {
@override @override
Widget build(BuildContext context) { 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( return ListenableBuilder(
listenable: settingsController, listenable: settingsController,
builder: (BuildContext context, Widget? child) { builder: (BuildContext context, Widget? child) {
return MaterialApp( 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', restorationScopeId: 'app',
supportedLocales: const [ supportedLocales: const [
Locale('en', ''), // English, no country code 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(), theme: ThemeData(),
darkTheme: ThemeData.dark(), darkTheme: ThemeData.dark(),
themeMode: settingsController.themeMode, themeMode: settingsController.themeMode,
// Define a function to handle named routes in order to support
// Flutter web url navigation and deep linking.
onGenerateRoute: (RouteSettings routeSettings) { onGenerateRoute: (RouteSettings routeSettings) {
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
settings: routeSettings, settings: routeSettings,

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

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

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

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:pi_dashboard/logger.dart';
import 'settings_service.dart'; import 'settings_service.dart';
@ -38,14 +39,17 @@ class SettingsController with ChangeNotifier {
Future<void> setHostname(String newHostname) async { Future<void> setHostname(String newHostname) async {
_hostname = newHostname; _hostname = newHostname;
await _setKey("hostname", hostname); await _setKey("hostname", hostname);
Log().debug("Hostname update: $hostname");
} }
Future<void> setUsername(String newUsername) async { Future<void> setUsername(String newUsername) async {
_username = newUsername; _username = newUsername;
await _setKey("username", username); await _setKey("username", username);
Log().debug("username update: $username");
} }
Future<void> setPassword(String newPassword) async { Future<void> setPassword(String newPassword) async {
_password = newPassword; _password = newPassword;
await _setKey("password", password); await _setKey("password", password);
Log().debug("password update");
} }
/// Update and persist the ThemeMode based on the user's selection. /// Update and persist the ThemeMode based on the user's selection.
Future<void> updateThemeMode(ThemeMode? newThemeMode) async { 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 /// When a user changes a setting, the SettingsController is updated and
/// Widgets that listen to the SettingsController are rebuilt. /// Widgets that listen to the SettingsController are rebuilt.
class SettingsView extends StatelessWidget { 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) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
@ -70,8 +70,7 @@ final SettingsController controller;
onChanged: controller.setPassword, onChanged: controller.setPassword,
), ),
], ],
) ),
), ),
); );
} }

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

Loading…
Cancel
Save