Skip to content

Commit

Permalink
* Refactored navdrawer layout code
Browse files Browse the repository at this point in the history
* Added Files view
* Added ability to reorder preserts in the settings
* Added multicam support
* Fixed NonPrinting FAB menu
* Replaced SpeedDial Lib
  • Loading branch information
Clon1998 committed Sep 29, 2021
1 parent 8d3380c commit e8d82fe
Show file tree
Hide file tree
Showing 31 changed files with 953 additions and 431 deletions.
2 changes: 2 additions & 0 deletions lib/app/app_setup.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:mobileraker/dto/machine/printer_setting.dart';
import 'package:mobileraker/dto/machine/temperature_preset.dart';
import 'package:mobileraker/dto/machine/webcam_setting.dart';
import 'package:mobileraker/service/machine_service.dart';
import 'package:mobileraker/ui/views/files/details/file_details_view.dart';
import 'package:mobileraker/ui/views/files/files_view.dart';
import 'package:mobileraker/ui/views/fullcam/full_cam_view.dart';
import 'package:mobileraker/ui/views/overview/overview_view.dart';
Expand All @@ -26,6 +27,7 @@ import 'package:stacked_services/stacked_services.dart';
MaterialRoute(page: PrintersAdd),
MaterialRoute(page: PrintersEdit),
MaterialRoute(page: FilesView),
MaterialRoute(page: FileDetailView),
], dependencies: [
LazySingleton(classType: NavigationService),
LazySingleton(classType: SnackbarService),
Expand Down
20 changes: 10 additions & 10 deletions lib/WebSocket.dart → lib/datasource/websocket_wrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ class WebSocketWrapper {
BehaviorSubject<WebSocketState> stateStream =
BehaviorSubject.seeded(WebSocketState.disconnected);

WebSocketState get state => stateStream.value;
WebSocketState get _state => stateStream.value;

set state(WebSocketState newState) {
_logger.i("$state ➝ $newState");
set _state(WebSocketState newState) {
_logger.i("$_state ➝ $newState");
stateStream.add(newState);
}

Expand Down Expand Up @@ -66,7 +66,7 @@ class WebSocketWrapper {

_tryConnect() {
_logger.i("Trying to connect to $url with APIkey: `${apiKey??'NO-APIKEY'}`");
state = WebSocketState.connecting;
_state = WebSocketState.connecting;
reset();

WebSocket.connect(url.toString(), headers: _headers)
Expand All @@ -86,8 +86,8 @@ class WebSocketWrapper {
);
// Send a req msg to be sure we are connected!

if (state != WebSocketState.connected) {
state = WebSocketState.connected;
if (_state != WebSocketState.connected) {
_state = WebSocketState.connected;
}
}, onError: _onWSError);
}
Expand All @@ -113,7 +113,7 @@ class WebSocketWrapper {
/// Ensures that the ws is still connected.
/// ----------------------------------------------------------
ensureConnection() {
if (state != WebSocketState.connected && state != WebSocketState.connecting)
if (_state != WebSocketState.connected && _state != WebSocketState.connecting)
initCommunication();
}

Expand Down Expand Up @@ -176,7 +176,7 @@ class WebSocketWrapper {
_onWSError(error) {
_logger.e("WS-Stream error: $error");
errorReason = error;
state = WebSocketState.error;
_state = WebSocketState.error;
}

bool get requiresAPIKey {
Expand All @@ -192,11 +192,11 @@ class WebSocketWrapper {
}

_onWSClosesNormal() {
var t = state;
var t = _state;
if (t != WebSocketState.error) {
t = WebSocketState.disconnected;
}
if (!stateStream.isClosed) state = t;
if (!stateStream.isClosed) _state = t;
initCommunication();
_logger.i("WS-Stream close normal!");
}
Expand Down
32 changes: 28 additions & 4 deletions lib/dto/files/gcode_file.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ class GCodeFile {
/// Path to the location/directory where the file is located
String parentPath;


GCodeFile({required this.name, required this.size, required this.modified, required this.parentPath});
GCodeFile(
{required this.name,
required this.size,
required this.modified,
required this.parentPath});

GCodeFile.fromJson(Map<String, dynamic> json, this.parentPath) {
this.name = json['filename'];
Expand Down Expand Up @@ -101,8 +104,29 @@ class GCodeFile {

String? get smallImagePath {
//ToDo: Filter for small <.<
if (thumbnails.isNotEmpty)
return thumbnails.first.relativePath;
if (thumbnails.isNotEmpty) return thumbnails.first.relativePath;
}

String? get bigImagePath {
//ToDo: Filter for big <.<
if (thumbnails.isNotEmpty) return thumbnails.last.relativePath;
}

DateTime? get modifiedDate {
return DateTime.fromMillisecondsSinceEpoch(modified.toInt() * 1000);
}

DateTime? get lastPrintDate {
return DateTime.fromMillisecondsSinceEpoch(
(printStartTime?.toInt() ?? 0) * 1000);
}

/// combines parentpath and name to the correct path to request a print!
String get pathForPrint {
List<String> split = parentPath.split('/');
split.removeAt(0); // remove 'gcodes'
split.add(name);
return split.join('/');
}

@override
Expand Down
43 changes: 2 additions & 41 deletions lib/dto/machine/printer.dart
Original file line number Diff line number Diff line change
@@ -1,28 +1,8 @@
import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:mobileraker/dto/config/config_file.dart';

enum PrinterAxis { X, Y, Z, E }
enum PrinterState { ready, error, shutdown, startup, disconnected }
enum PrintState { standby, printing, paused, complete, error }

String printerStateName(PrinterState printerState) {
switch (printerState) {
case PrinterState.ready:
return "Ready";
case PrinterState.shutdown:
return "Shutdown";
case PrinterState.startup:
return "Starting";
case PrinterState.disconnected:
return "Disconnected";
case PrinterState.error:
default:
return "Error";
}
}

String printStateName(PrintState printState) {
switch (printState) {
case PrintState.standby:
Expand All @@ -40,8 +20,6 @@ String printStateName(PrintState printState) {
}

class Printer {
PrinterState state = PrinterState.error; //Matches ServerState

Toolhead toolhead = Toolhead();
Extruder extruder = Extruder();
HeaterBed heaterBed = HeaterBed();
Expand All @@ -61,8 +39,6 @@ class Printer {
List<String> queryableObjects = [];
List<String> gcodeMacros = [];

String get stateName => printerStateName(state);

double get zOffset => gCodeMove.homingOrigin[2];

DateTime? get eta {
Expand All @@ -74,31 +50,16 @@ class Printer {
return null;
}

static Color stateToColor(PrinterState state) {
switch (state) {
case PrinterState.ready:
return Colors.green;
case PrinterState.error:
return Colors.red;
case PrinterState.shutdown:
case PrinterState.startup:
case PrinterState.disconnected:
default:
return Colors.orange;
}
}

@override
String toString() {
return 'Printer{state: $state, toolhead: $toolhead, extruder: $extruder, heaterBed: $heaterBed, printFan: $printFan, gCodeMove: $gCodeMove, print: $print, configFile: $configFile, fans: $fans, temperatureSensors: $temperatureSensors, outputPins: $outputPins, virtualSdCard: $virtualSdCard, queryableObjects: $queryableObjects, gcodeMacros: $gcodeMacros}';
return 'Printer{toolhead: $toolhead, extruder: $extruder, heaterBed: $heaterBed, printFan: $printFan, gCodeMove: $gCodeMove, print: $print, configFile: $configFile, fans: $fans, temperatureSensors: $temperatureSensors, outputPins: $outputPins, virtualSdCard: $virtualSdCard, queryableObjects: $queryableObjects, gcodeMacros: $gcodeMacros}';
}

@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Printer &&
runtimeType == other.runtimeType &&
state == other.state &&
toolhead == other.toolhead &&
extruder == other.extruder &&
heaterBed == other.heaterBed &&
Expand All @@ -115,7 +76,6 @@ class Printer {

@override
int get hashCode =>
state.hashCode ^
toolhead.hashCode ^
extruder.hashCode ^
heaterBed.hashCode ^
Expand Down Expand Up @@ -458,6 +418,7 @@ class TemperatureSensor {

class OutputPin {
String name;

// This value is between 0-1
double value = 0.0;

Expand Down
2 changes: 1 addition & 1 deletion lib/dto/machine/printer_setting.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'package:hive/hive.dart';
import 'package:mobileraker/WebSocket.dart';
import 'package:mobileraker/datasource/websocket_wrapper.dart';
import 'package:mobileraker/dto/machine/temperature_preset.dart';
import 'package:mobileraker/dto/machine/webcam_setting.dart';
import 'package:mobileraker/service/file_service.dart';
Expand Down
58 changes: 55 additions & 3 deletions lib/dto/server/klipper.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,67 @@
import 'package:mobileraker/dto/machine/printer.dart';
import 'package:flutter/material.dart';

enum KlipperState { ready, error, shutdown, startup, disconnected }

class KlipperInstance {
bool klippyConnected;

PrinterState klippyState; //Matches Printer state
KlipperState klippyState; //Matches Printer state
String get klippyStateName => printerStateName(klippyState);

List<String> plugins;

KlipperInstance(
{this.klippyConnected = false,
this.klippyState = PrinterState.error,
this.klippyState = KlipperState.error,
this.plugins = const []});

String get stateName => printerStateName(klippyState);

static Color stateToColor(KlipperState state) {
switch (state) {
case KlipperState.ready:
return Colors.green;
case KlipperState.error:
return Colors.red;
case KlipperState.shutdown:
case KlipperState.startup:
case KlipperState.disconnected:
default:
return Colors.orange;
}
}

static String printerStateName(KlipperState printerState) {
switch (printerState) {
case KlipperState.ready:
return "Ready";
case KlipperState.shutdown:
return "Shutdown";
case KlipperState.startup:
return "Starting";
case KlipperState.disconnected:
return "Disconnected";
case KlipperState.error:
default:
return "Error";
}
}

@override
String toString() {
return 'KlipperInstance{klippyConnected: $klippyConnected, klippyState: $klippyState, plugins: $plugins}';
}

@override
bool operator ==(Object other) =>
identical(this, other) ||
other is KlipperInstance &&
runtimeType == other.runtimeType &&
klippyConnected == other.klippyConnected &&
klippyState == other.klippyState &&
plugins == other.plugins;

@override
int get hashCode =>
klippyConnected.hashCode ^ klippyState.hashCode ^ plugins.hashCode;
}
47 changes: 33 additions & 14 deletions lib/service/file_service.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'dart:async';

import 'package:enum_to_string/enum_to_string.dart';
import 'package:mobileraker/WebSocket.dart';
import 'package:mobileraker/datasource/websocket_wrapper.dart';
import 'package:mobileraker/app/app_setup.logger.dart';
import 'package:mobileraker/dto/files/folder.dart';
import 'package:mobileraker/dto/files/gcode_file.dart';
Expand All @@ -27,22 +27,20 @@ class FileService {
final WebSocketWrapper _webSocket;
final _logger = getLogger('FileService');

// final BehaviorSubject<List<GCode>> fileStream =
// BehaviorSubject<List<GCode>>();

FileService(this._webSocket) {
_webSocket.addMethodListener(_onFileListChanged, "notify_filelist_changed");

_webSocket.stateStream.listen((value) {
switch (value) {
case WebSocketState.connected:
// _fetchAvailableFiles(FileRoot.gcodes);

// _fetchDirectoryInfo('gcodes', true);
break;
default:
}
});
// _webSocket.stateStream.listen((value) {
// switch (value) {
// case WebSocketState.connected:
// // _fetchAvailableFiles(FileRoot.gcodes);
//
// // _fetchDirectoryInfo('gcodes', true);
// break;
// default:
// }
// });
}

_onFileListChanged(Map<String, dynamic> rawMessage) {
Expand All @@ -54,7 +52,7 @@ class FileService {
Future<FolderReqWrapper> fetchDirectoryInfo(String path,
[bool extended = false]) async {
Completer<FolderReqWrapper> reqCompleter = Completer();
_logger.i('Fetching for $path [extended:$extended]');
_logger.i('Fetching for `$path` [extended:$extended]');


_webSocket.sendObject("server.files.get_directory",
Expand All @@ -69,6 +67,18 @@ class FileService {
params: {'root': EnumToString.convertToString(root)});
}


Future<GCodeFile> getGCodeMetadata(String filename) async {
Completer<GCodeFile> reqCompleter = Completer();
_logger.i('Getting meta for file: `$filename`');


_webSocket.sendObject("server.files.metadata",
(response) => _parseFileMeta(response, filename, reqCompleter),
params: {'filename': filename});
return reqCompleter.future;
}

_parseResult(response, FileRoot root) {
// List<dynamic> fileList = response; // Just add an type
//
Expand Down Expand Up @@ -119,6 +129,15 @@ class FileService {

completer.complete(FolderReqWrapper(forPath,listOfFolder, listOfFiles));
}

_parseFileMeta(response, String forFile, Completer<GCodeFile> completer) {
var split = forFile.split('/');
split.removeLast();
split.insert(0, 'gcodes');// we need to add the gcodes here since the getMetaInfo omits gcodes path.

;
completer.complete(GCodeFile.fromJson(response, split.join('/')));
}
}

class FolderReqWrapper {
Expand Down
Loading

0 comments on commit e8d82fe

Please sign in to comment.