2022-09-16 11:19:46 +02:00
using System ;
2021-05-13 20:03:07 +02:00
using System.Collections.Generic ;
using System.Runtime.Serialization ;
2022-08-30 15:42:25 +02:00
using System.Threading ;
using Plugin.BLE.Abstractions.Contracts ;
using Plugin.Connectivity ;
using Serilog ;
using Serilog.Core ;
using Serilog.Events ;
using Serilog.Filters ;
2021-05-13 20:03:07 +02:00
using TINK.Model.Connector ;
using TINK.Model.Device ;
using TINK.Model.Logging ;
using TINK.Model.Services.CopriApi.ServerUris ;
2022-08-30 15:42:25 +02:00
using TINK.Model.Settings ;
using TINK.Model.Station ;
using TINK.Model.User.Account ;
2021-05-13 20:03:07 +02:00
using TINK.Services ;
2022-08-30 15:42:25 +02:00
using TINK.Services.BluetoothLock ;
2021-05-13 20:03:07 +02:00
using TINK.Services.BluetoothLock.BLE ;
2022-08-30 15:42:25 +02:00
using TINK.Services.BluetoothLock.Crypto ;
using TINK.Services.Geolocation ;
using TINK.Services.Logging ;
2022-04-10 17:38:34 +02:00
using TINK.Services.Permissions ;
2022-08-30 15:42:25 +02:00
using TINK.Services.ThemeNS ;
using TINK.Settings ;
using TINK.ViewModel.Map ;
using TINK.ViewModel.Settings ;
2021-05-13 20:03:07 +02:00
namespace TINK.Model
{
2022-09-06 16:08:19 +02:00
[DataContract]
public class TinkApp : ITinkApp
{
/// <summary> Delegate used by login view to commit user name and password. </summary>
/// <param name="p_strMailAddress">Mail address used as id login.</param>
/// <param name="p_strPassword">Password for login.</param>
/// <returns>True if setting credentials succeeded.</returns>
public delegate bool SetCredentialsDelegate ( string p_strMailAddress , string p_strPassword ) ;
/// <summary>Returns the id of the app (sharee.bike) to be identified by copri.</summary>
public static string MerchantId { get ; private set ; }
/// <summary>
/// Holds status about whants new page.
/// </summary>
public WhatsNew WhatsNew { get ; private set ; }
/// <summary>Holds uris of copri servers. </summary>
public CopriServerUriList Uris { get ; private set ; }
/// <summary> Holds the filters loaded from settings. </summary>
public IGroupFilterSettings FilterGroupSetting { get ; set ; }
2022-10-17 18:45:38 +02:00
/// <summary> Settings determining the startup behavior of the app.</summary>
public IStartupSettings StartupSettings { get ; private set ; }
2022-09-06 16:08:19 +02:00
/// <summary> Holds the filter which is applied on the map view. Either TINK or Konrad stations are displayed. </summary>
private IGroupFilterMapPage m_oFilterDictionaryMapPage ;
/// <summary> Holds the filter which is applied on the map view. Either TINK or Konrad stations are displayed. </summary>
public IGroupFilterMapPage GroupFilterMapPage
{
get = > m_oFilterDictionaryMapPage ;
set = > m_oFilterDictionaryMapPage = value ? ? new GroupFilterMapPage ( ) ;
}
/// <summary> Value indicating whether map is centerted to current position or not. </summary>
public bool CenterMapToCurrentLocation { get ; set ; }
/// <summary> Holds the map area to display when starting app for first time/ when center map to is off. </summary>
private Xamarin . Forms . GoogleMaps . MapSpan HomeMapSpan { get ; }
/// <summary> Holds the map area where user is or was located or null if this position is unknown. </summary>
public Xamarin . Forms . GoogleMaps . MapSpan UserMapSpan { get ; set ; } = null ;
/// <summary> Holds the map span to display either default span or span centered to current position depending on option <see cref="CenterMapToCurrentLocation"/>.</summary>
public Xamarin . Forms . GoogleMaps . MapSpan ActiveMapSpan
2022-10-17 18:45:38 +02:00
{
get
{
if ( CenterMapToCurrentLocation = = false )
{
return HomeMapSpan ;
}
return UserMapSpan ? ? HomeMapSpan ;
}
}
2022-09-06 16:08:19 +02:00
/// <summary> Gets the minimum logging level. </summary>
public LogEventLevel MinimumLogEventLevel { get ; set ; }
/// <summary> Gets a value indicating whether reporting level is verbose or not.</summary>
public bool IsReportLevelVerbose { get ; set ; }
/// <summary> Holds the uri which is applied after restart. </summary>
public Uri NextActiveUri { get ; set ; }
/// <summary> Saves object to file. </summary>
public void Save ( )
= > JsonSettingsDictionary . Serialize (
SettingsFileFolder ,
new Dictionary < string , string > ( )
. SetGroupFilterMapPage ( GroupFilterMapPage )
. SetCopriHostUri ( NextActiveUri . AbsoluteUri )
. SetPollingParameters ( Polling )
. SetGroupFilterSettings ( FilterGroupSetting )
2022-10-17 18:45:38 +02:00
. SetStartupSettings ( StartupSettings )
2022-09-06 16:08:19 +02:00
. SetAppVersion ( AppVersion )
. SetMinimumLoggingLevel ( MinimumLogEventLevel )
. SetIsReportLevelVerbose ( IsReportLevelVerbose )
. SetExpiresAfter ( ExpiresAfter )
. SetWhatsNew ( AppVersion )
. SetActiveLockService ( LocksServices . Active . GetType ( ) . FullName )
. SetActiveGeolocationService ( GeolocationServices . Active . GetType ( ) . FullName )
. SetCenterMapToCurrentLocation ( CenterMapToCurrentLocation )
. SetLogToExternalFolder ( LogToExternalFolder )
. SetConnectTimeout ( LocksServices . Active . TimeOut . MultiConnect )
. SetIsSiteCachingOn ( IsSiteCachingOn )
. SetActiveTheme ( Themes . Active ) ) ;
/// <summary>
/// Update connector from filters when
/// - login state changes
/// - view is toggled (TINK to Kornrad and vice versa)
/// </summary>
public void UpdateConnector ( )
{
// Create filtered connector.
m_oConnector = FilteredConnectorFactory . Create (
FilterGroupSetting . DoFilter ( ActiveUser . DoFilter ( GroupFilterMapPage . DoFilter ( ) ) ) ,
m_oConnector . Connector ) ;
}
/// <summary>Polling periode.</summary>
public PollingParameters Polling { get ; set ; }
public TimeSpan ExpiresAfter { get ; set ; }
/// <summary> Holds the version of the app.</summary>
public Version AppVersion { get ; }
/// <summary>
/// Holds the default polling value.
/// </summary>
2021-06-26 20:57:55 +02:00
#if USCSHARP9
public TimeSpan DefaultPolling = > new ( 0 , 0 , 10 ) ;
#else
2022-09-06 16:08:19 +02:00
public TimeSpan DefaultPolling = > new TimeSpan ( 0 , 0 , 10 ) ;
2021-06-26 20:57:55 +02:00
#endif
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> Constructs TinkApp object. </summary>
/// <param name="settings"></param>
/// <param name="accountStore"></param>
/// <param name="passwordValidator"></param>
/// <param name="p_oConnectorFactory"></param>
/// <param name="geolocationService">Null in productive context. Service to querry geoloation for testing purposes. Parameter can be made optional.</param>
/// <param name="locksService">Null in productive context. Service to control locks/ get locks information for testing proposes. Parameter can be made optional.</param>
/// <param name="device">Object allowing platform specific operations.</param>
/// <param name="specialFolder"></param>
/// <param name="p_oDateTimeProvider"></param>
/// <param name="isConnectedFunc">True if connector has access to copri server, false if cached values are used.</param>
/// <param name="currentVersion">Version of the app. If null version is set to a fixed dummy value (3.0.122) for testing purposes.</param>
/// <param name="lastVersion">Version of app which was used before this session, null if app is installed for the first time.</param>
/// <param name="whatsNewShownInVersion"> Holds
/// - the version when whats new info was shown last or
/// - version of application used last if whats new functionality was not implemented in this version or
/// - null if app is installed for the first time.
/// /// </param>
public TinkApp (
Settings . Settings settings ,
IStore accountStore ,
Func < bool > isConnectedFunc ,
Func < bool , Uri , string /* session cookie*/ , string /* mail address*/ , TimeSpan , IConnector > connectorFactory ,
string merchantId ,
IBluetoothLE bluetoothService ,
ILocationPermission locationPermissionsService ,
IServicesContainer < IGeolocation > locationServicesContainer ,
ILocksService locksService ,
ISmartDevice device ,
ISpecialFolder specialFolder ,
ICipher cipher ,
ITheme theme ,
object arendiCentral = null ,
Action < SendOrPostCallback , object > postAction = null ,
Version currentVersion = null ,
Version lastVersion = null ,
Version whatsNewShownInVersion = null ,
AppFlavor flavor = AppFlavor . ShareeBike )
{
PostAction = postAction
? ? ( ( d , obj ) = > d ( obj ) ) ;
ConnectorFactory = connectorFactory
2023-02-22 14:03:35 +01:00
? ? throw new ArgumentException ( $"Can not instantiate {nameof(TinkApp)}- object. No connector factory object available." ) ;
2022-09-06 16:08:19 +02:00
MerchantId = merchantId
2023-02-22 14:03:35 +01:00
? ? throw new ArgumentException ( $"Can not instantiate {nameof(TinkApp)}- object. No merchant id available." ) ;
if ( settings = = null )
throw new ArgumentException ( $"Can not instantiate {nameof(TinkApp)}- object. Settings must not be null." ) ;
2022-09-06 16:08:19 +02:00
Cipher = cipher ? ? new Cipher ( ) ;
Flavor = flavor ;
2022-09-16 11:19:46 +02:00
// Log application and environment information.
new AppAndEnvironmentInfo ( ) . LogHeader ( device , flavor , currentVersion ) ;
2022-09-06 16:08:19 +02:00
var locksServices = locksService ! = null
? new HashSet < ILocksService > { locksService }
: new HashSet < ILocksService > {
new LockItByScanServiceEventBased (
Cipher ,
bluetoothService ,
async ( ) = > device . Platform = = Xamarin . Essentials . DevicePlatform . Android & & await locationPermissionsService . CheckStatusAsync ( ) ! = Status . Granted ,
( ) = > device . Platform = = Xamarin . Essentials . DevicePlatform . Android & & ! locationServicesContainer . Active . IsGeolcationEnabled ) ,
new LockItByScanServicePolling (
Cipher ,
bluetoothService ,
async ( ) = > device . Platform = = Xamarin . Essentials . DevicePlatform . Android & & await locationPermissionsService . CheckStatusAsync ( ) ! = Status . Granted ,
( ) = > device . Platform = = Xamarin . Essentials . DevicePlatform . Android & & ! locationServicesContainer . Active . IsGeolcationEnabled ) ,
new LockItByGuidService ( Cipher ) ,
2021-05-13 20:03:07 +02:00
#if BLUETOOTHLE // Requires LockItBluetoothle library.
new Bluetoothle . LockItByGuidService ( Cipher ) ,
#endif
#if ARENDI // Requires LockItArendi library.
new Arendi . LockItByGuidService ( Cipher , arendiCentral ) ,
new Arendi . LockItByScanService ( Cipher , arendiCentral ) ,
#endif
new LocksServiceInReach ( ) ,
2022-09-06 16:08:19 +02:00
new LocksServiceOutOfReach ( ) ,
} ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
LocksServices = new LocksServicesContainerMutable (
lastVersion > = new Version ( 3 , 0 , 173 ) ? settings . ActiveLockService : LocksServicesContainerMutable . DefaultLocksservice ,
locksServices ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
LocksServices . SetTimeOut ( settings . ConnectTimeout ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
Themes = new ServicesContainerMutable (
new HashSet < string > {
ThemeSet . Konrad . ToString ( ) ,
ThemeSet . ShareeBike . ToString ( ) ,
ThemeSet . LastenradBayern . ToString ( )
} ,
Enum . TryParse ( settings . ActiveTheme , true , out ThemeSet active ) ? active . ToString ( ) : ThemeSet . ShareeBike . ToString ( ) ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
GeolocationServices = locationServicesContainer
? ? throw new ArgumentException ( $"Can not instantiate {nameof(TinkApp)}- object. No geolocation services container object available." ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
FilterGroupSetting = settings . GroupFilterSettings ;
GroupFilterMapPage = settings . GroupFilterMapPage ;
2021-05-13 20:03:07 +02:00
2022-10-17 18:45:38 +02:00
StartupSettings = settings . StartupSettings ;
2022-09-06 16:08:19 +02:00
CenterMapToCurrentLocation = settings . CenterMapToCurrentLocation ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
HomeMapSpan = settings . MapSpan ;
2021-11-14 23:27:29 +01:00
2022-09-06 16:08:19 +02:00
SmartDevice = device
? ? throw new ArgumentException ( "Can not instantiate TinkApp- object. No device information provider available." ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
if ( specialFolder = = null )
{
throw new ArgumentException ( "Can not instantiate TinkApp- object. No special folder provider available." ) ;
}
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
// Set logging level.
Level . MinimumLevel = settings . MinimumLogEventLevel ;
2022-08-30 15:42:25 +02:00
2022-09-06 16:08:19 +02:00
LogToExternalFolder = settings . LogToExternalFolder ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
IsSiteCachingOn = settings . IsSiteCachingOn ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
ExternalFolder = specialFolder . GetExternalFilesDir ( ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
SettingsFileFolder = specialFolder . GetInternalPersonalDir ( ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
ActiveUser = new User . User (
accountStore . GetType ( ) . Name = = "StoreLegacy" ? new Store ( ) : accountStore ,
accountStore . Load ( ) . Result ,
device . Identifier ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
this . isConnectedFunc = isConnectedFunc ? ? ( ( ) = > CrossConnectivity . Current . IsConnected ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
ExpiresAfter = settings . ExpiresAfter ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
// Create filtered connector for offline mode.
m_oConnector = FilteredConnectorFactory . Create (
FilterGroupSetting . DoFilter ( GroupFilterMapPage . DoFilter ( ) ) ,
ConnectorFactory ( GetIsConnected ( ) , settings . ActiveUri , ActiveUser . SessionCookie , ActiveUser . Mail , ExpiresAfter ) ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
// Get uris from file.
// Initialize all settings to defaults
// Process uris.
Uris = new CopriServerUriList ( settings . ActiveUri ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
NextActiveUri = Uris . ActiveUri ;
2021-05-13 20:03:07 +02:00
2023-02-22 14:03:35 +01:00
if ( settings . PollingParameters = = null )
throw new ArgumentException ( $"Can not instantiate {nameof(TinkApp)}- object. Polling parameters must never be null." ) ;
Polling = ( lastVersion ! = null & & lastVersion < new Version ( 3 , 0 , 358 ) )
? PollingParameters . Default // Default polling periode was 10s up to 3.0.357. Is 60s for later versions.
: settings . PollingParameters ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
AppVersion = currentVersion ? ? new Version ( 3 , 0 , 122 ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
MinimumLogEventLevel = settings . MinimumLogEventLevel ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
IsReportLevelVerbose = settings . IsReportLevelVerbose ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
WhatsNew = new WhatsNew ( AppVersion , lastVersion , whatsNewShownInVersion , Flavor , SmartDevice . Platform ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
if ( Themes . Active . GetType ( ) . FullName = = typeof ( Themes . ShareeBike ) . FullName )
{
// Nothing to do.
// Theme to activate is default theme.
return ;
}
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
// Set active app theme from settings.
// Value might differ from default scheme value defined in ResourceDictionary.MergedDictionaries (App.xaml)
if ( theme = = null )
{
Log . ForContext < TinkApp > ( ) . Error ( "No merged dictionary available." ) ;
return ;
}
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
theme . SetActiveTheme ( Themes . Active ) ;
}
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> Holds the user of the app. </summary>
[DataMember]
public User . User ActiveUser { get ; }
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> Reference of object which provides device information. </summary>
public ISmartDevice SmartDevice { get ; }
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> Holds delegate to determine whether device is connected or not.</summary>
private readonly Func < bool > isConnectedFunc ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> Gets whether device is connected to internet or not. </summary>
public bool GetIsConnected ( ) = > isConnectedFunc ( ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> Holds the folder where settings files are stored. </summary>
public string SettingsFileFolder { get ; }
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> Holds folder parent of the folder where log files are stored. </summary>
public string LogFileParentFolder = > LogToExternalFolder & & ! string . IsNullOrEmpty ( ExternalFolder ) ? ExternalFolder : SettingsFileFolder ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> Holds a value indicating whether to log to external or internal folder. </summary>
public bool LogToExternalFolder { get ; set ; }
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> Holds a value indicating whether Site caching is on or off. </summary>
public bool IsSiteCachingOn { get ; set ; }
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> External folder. </summary>
public string ExternalFolder { get ; }
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
public ICipher Cipher { get ; }
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> Name of the station which is selected. </summary>
public IStation SelectedStation { get ; set ; } = new NullStation ( ) ;
2021-06-26 20:57:55 +02:00
2022-09-06 16:08:19 +02:00
/// <summary> Holds the stations availalbe. </summary>
public IEnumerable < IStation > Stations { get ; set ; } = new List < Station . Station > ( ) ;
2021-05-13 20:03:07 +02:00
2022-09-06 16:08:19 +02:00
public IResourceUrls ResourceUrls { get ; set ; } = new ResourceUrls ( ) ;
2022-01-22 18:28:01 +01:00
2022-09-06 16:08:19 +02:00
/// <summary> Action to post to GUI thread.</summary>
public Action < SendOrPostCallback , object > PostAction { get ; }
/// <summary> Function which creates a connector depending on connected status.</summary>
private Func < bool , Uri , string /*userAgent*/ , string /*sessionCookie*/ , TimeSpan , IConnector > ConnectorFactory { get ; }
/// <summary> Holds the object which provides offline data.</summary>
private IFilteredConnector m_oConnector ;
/// <summary> Holds the system to copri.</summary>
public IFilteredConnector GetConnector ( bool isConnected )
{
if ( m_oConnector . IsConnected = = isConnected
& & m_oConnector . Command . SessionCookie = = ActiveUser . SessionCookie )
{
// Neither connection nor logged in stated changed.
return m_oConnector ;
}
// Connected state changed. New connection object has to be created.
m_oConnector = FilteredConnectorFactory . Create (
FilterGroupSetting . DoFilter ( ActiveUser . DoFilter ( GroupFilterMapPage . DoFilter ( ) ) ) ,
ConnectorFactory (
isConnected ,
Uris . ActiveUri ,
ActiveUser . SessionCookie ,
ActiveUser . Mail ,
ExpiresAfter ) ) ;
return m_oConnector ;
}
/// <summary> Manages the different types of LocksService objects.</summary>
public LocksServicesContainerMutable LocksServices { get ; set ; }
/// <summary> Holds available app themes.</summary>
public IServicesContainer < IGeolocation > GeolocationServices { get ; }
/// <summary> Holds the flavor of the app, i.e. specifies if app is sharee.bike, Mein konrad or Lastenrad Bayern.</summary>
public AppFlavor Flavor { get ; private set ; }
/// <summary> Manages the different types of LocksService objects.</summary>
public ServicesContainerMutable Themes { get ; private set ; }
/// <summary> Object to switch logging level. </summary>
private LoggingLevelSwitch m_oLoggingLevelSwitch ;
/// <summary>
/// Object to allow swithing logging level
/// </summary>
public LoggingLevelSwitch Level
{
get
{
if ( m_oLoggingLevelSwitch = = null )
{
m_oLoggingLevelSwitch = new LoggingLevelSwitch
{
// Set warning level to error.
MinimumLevel = Settings . Settings . DEFAULTLOGGINLEVEL
} ;
}
return m_oLoggingLevelSwitch ;
}
}
/// <summary> Updates logging level. </summary>
/// <param name="minimumLevel">New level to set.</param>
public void UpdateLoggingLevel ( LogEventLevel minimumLevel )
{
if ( Level . MinimumLevel = = minimumLevel )
{
// Nothing to do.
return ;
}
Log . CloseAndFlush ( ) ; // Close before modifying logger configuration. Otherwise a sharing vialation occurs.
Level . MinimumLevel = minimumLevel ;
SetupLogging ( Level , LogFileParentFolder ) ;
}
/// <summary>
/// Sets up logging.
/// </summary>
/// <param name="levelSwitch">Logging level to use.</param>
/// <param name="logFilePath">Path to logging file.</param>
public static void SetupLogging (
LoggingLevelSwitch levelSwitch ,
string logFilePath )
{
2022-09-16 11:19:46 +02:00
bool LogToFileFilter ( LogEvent e )
{
if ( e . Level > = levelSwitch . MinimumLevel )
{
// If level is above global logging level do log.
return true ;
}
if ( ! e . Properties . ContainsKey ( Constants . SourceContextPropertyName ) )
{
// Do not log if source context is not available.
return false ;
}
var sourceContex = e . Properties [ Constants . SourceContextPropertyName ] . ToString ( ) ;
if ( ( e . Level = = LogEventLevel . Information ) & &
( sourceContex . Contains ( typeof ( AppAndEnvironmentInfo ) . Namespace ) /* Log App and enviroment info. */
| | sourceContex . Contains ( typeof ( ViewModel . Bikes . Bike . BluetoothLock . RequestHandler . Base ) . Namespace /* Log info-level messages to provide context for bluetooth log. */ ) ) )
{
return true ;
}
if ( e . Level > = LogEventLevel . Debug
& & sourceContex . Contains ( typeof ( LockItBase ) . Namespace /*Scanning, connect and management functionality */ ) )
{
return true ;
}
return false ;
}
2022-09-06 16:08:19 +02:00
Log . Logger = new LoggerConfiguration ( )
2022-09-16 11:19:46 +02:00
. MinimumLevel . Verbose ( )
. WriteTo . Logger ( consoleLoggerConfig = > consoleLoggerConfig
. MinimumLevel . Information ( )
. WriteTo . Debug ( )
)
. WriteTo . Logger ( fileLoggerConfig = > fileLoggerConfig
. Filter . ByIncludingOnly ( e = > LogToFileFilter ( e ) )
. WriteTo . File ( logFilePath , Logging . RollingInterval . Session )
)
. WriteTo . Logger ( copriLoggerConfig = > copriLoggerConfig
. MinimumLevel . Debug ( )
. Filter . ByIncludingOnly ( Matching . FromSource ( typeof ( LockItBase /*Scanning, connect and management functionality */ ) . Namespace ) )
2022-09-06 16:08:19 +02:00
. WriteTo . MemoryQueueSink ( )
)
. CreateLogger ( ) ;
}
}
2021-05-13 20:03:07 +02:00
}