Saving power on Ubuntu Server

I’ve been meaning to look into this for a while. My Ubuntu server acts as a NAS drive. As such it’s on all the time, but really it needn’t be. So let’s look at what we can do to save some energy by “hibernating” late in the evening and restarting early in the morning…

Let’s start with the /usr/sbin/rtcwake command. This application will tell your Linux OS to go into a sleep/hibernate state and you supply it with a time to wake back up, for example

/usr/sbin/rtcwake -m off 

The -m switch specifies the type of suspend. Options include

  • standby this option is the least energy efficient option and is the default option if you do not set the -m switch, it’s also very fast at resuming a system from sleep.
  • mem this option suspends to RAM, this puts everything into a low powered state (except RAM) and offers significant savings in energy.
  • disk this option suspends disk operations, the contents of memory are written to disk then restored when the computer wakes up.
  • off this option turns the computer off completely
  • no this option allows you to specify the awake time but doesn’t suspect the computer. The idea is that the user would put the machine into hibernation
    and rtcwake would then wake it up again at the specified point in time.

We might wish to set the resume time using either seconds (i.e. how many seconds in the future does the system resume) using the -s options, for example to wake up 10 hours after going to sleep we would specify 36000 seconds, like this

/usr/sbin/rtcwake -m off -s 36000

or to specify a time we use the -t switch which requires the number of seconds since Unix epoch (i.e. Jan 1st 1970, 00:00:00) so we still need to calculate to seconds

/usr/sbin/rtcwake -m off -t $(date +%s -d ‘tomorrow 07:00’)

If your hardware clock is set to local time, you’ll want to use the -l switch, for example

/usr/sbin/rtcwake -m off -l -t $(date +%s -d ‘tomorrow 07:00’)

Below is a script taken from StackOverflow. Just save this script as wakeup.sh or whatever file name and chmod to executable.

#!/bin/sh

# unix time in s that we should wake at
waketime=$(date +%s -d '07:00')

# make sure the time we got is in the future
if [ $(date +%s) -gt $waketime ]; then

        # if not add a day 60s * 60s * 24h
        waketime=$(($waketime + 86400))
fi

# time in S from now till then
dif=$(($waketime - $(date +%s)))

# tell the user
echo
echo "Current Time      :  $(date +%s)"
echo "Wake Time         :  $waketime"
echo "Seconds From Now  :  $dif"
echo
echo "Ctrl-C to Cancel in 5s"
echo
sleep 5

# sleep with rtcwake
/usr/sbin/rtcwake -m off -l -s $dif

echo "Shutdown."#!/bin/sh

But wait, we can run this rtcwake command (or the above script) manually but for my scenario I’d really want want it run automatically. So we add a cronjob as sudo (as rtcwake will need to be run as sudo) i.e.

sudo crontab -e

Now add the following

0 0 * * * /home/putridparrot/wakeup.sh > /home/putridparrot/wakeup.log

As per crontab expectations the arguments are as follows

  • MIN: Minute 0-60
  • HOUR: Hour, 24 hour clock hence 0-23
  • MDAY: Day of the Month, 1-31
  • MON: Month, 1-12 or jan, feb…dec
  • DOW: Day of the week, 0-6 or sun, mon, tue…sat
  • COMMAND: The command to run

So with this knowledge, our script will run at 12:00am every day. I found it useful to create a log of the output of the script, just to ensure I could see it had run. Remember > will create a new file overwriting any existing file or you could use >> to append to an existing file if you prefer (but then you might want a cronjob to delete the file periodically).

You can also check the syslog for CRON jobs via

grep CRON /var/log/syslog

Dependency injection using Shell in MAUI

The MauiAppBuilder (as seen in the MauiProgram class) i.e.

var builder = MauiApp.CreateBuilder();

exposes the property Services which is a collection of ServiceDescriptor objects. This is where we register our “services”. We can use AddSingleton or AddTransient or AddScoped.

So for example

builder.Services.AddSingleton<MainPage>();
builder.Services.AddSingleton<MainPageViewModel>();
  • AddSingleton
    As the name suggests, a single instance of a type is created across the lifetime of the application.
  • AddTransient
    A new instance of a type is created for each request, the equivalent of creating a new instance for every type that has a dependency, hence each gets a unique instance.
  • AddScoped
    A new instance of a type is created for a request and all dependencies within that request gets the same instance. For different requests a new instance is created, hence unique across requests.

Whilst the IoC container with MAUI Shell, isn’t as comprehensive in features as some containers, such as Autofac, it’s good enough for many. It does include constructor dependency injection so we will probably fulfil most use cases.

Okay, let’s assume with have a MainPage and on that we have a button which displays an AboutPage. As per the code above suggests. We can create a view model for each page, so we have a MainPageViewModel and AboutPageViewModel, then within the actual .xaml.cs of those pages, in the constructor we have code such as

public MainPage(MainPageViewModel vm)
{
   InitializeComponent();
   BindingContext = vm;
}


public AboutPage(AboutPageViewModel vm)
{
   InitializeComponent();
   BindingContext = vm;
}

Now all we need to do is register the pages and view models within the MauiProgram with the builder, so we have

builder.Services.AddSingleton<MainPage>();
builder.Services.AddSingleton<MainPageViewModel>();
builder.Services.AddTransient<AboutPage>();
builder.Services.AddTransient<AboutPageViewModel>();

When Maui starts up and loads MainPage.xaml it will inject the MainPageViewModel and also when we navigate to our AboutPage using something like the code below, again the view model is injected

[RelayCommand]
private async Task About() => await AppShell.Current.GoToAsync(nameof(AboutPage));

Note: The example uses the MVVM Community Toolkit, hence the RelayCommandAttribute.

We may need to resolve dependencies ourselves (in other words we’re unable to use the magic of something like constructor injection). Rather strangely I would have expected MAUI to already have code within for this, but it seems that current the solution is to create (or use an existing) ServiceProvider class. For example, the one shown below is taken from David Ortinau’s sample.

public static class ServiceProvider
{
   public static TService GetService<TService>()
      => Current.GetService<TService>();

   public static IServiceProvider Current
      =>
#if WINDOWS10_0_17763_0_OR_GREATER
	MauiWinUIApplication.Current.Services;
#elif ANDROID
        MauiApplication.Current.Services;
#elif IOS || MACCATALYST
	MauiUIApplicationDelegate.Current.Services;
#else
	null;
#endif
}

Now now we can use the static class ServiceProvider to get the Services, for example let’s remove the dependency injection in the AboutPage constructor and instead use the ServiceProvider like this

BindingContext = ServiceProvider.GetService<AboutPageViewModel>();

Ofcourse this is not so easily testable, but the option is there if required.

Navigating to different pages using MAUI and Shell

By default MAUI includes the Shell (see AppShell.xaml/AppShell.xaml.cs). We can use method on this object to navigate to pages in MAUI, for example if we add a simple AboutPage and want to navigate to it from a our view model we can write something like this

[RelayCommand]
private async Task About() => await AppShell.Current.GoToAsync(nameof(AboutPage));

Obviously the nameof(AboutPage) maps the the name we’ll be registering for the AboutPage.

Now we need to register the page within the shell, so go to AppShell.xaml.cs and add the following

Routing.RegisterRoute(nameof(AboutPage), typeof(AboutPage));

That’s all we need to do.

MVVM with the MVVM Community Toolkit

When you first create a MAUI application, you might be surprised to find there’s no view models setup by default. I guess this just allows us to see a bare bones application without any preference for MVVM libraries etc.

Let’s try out the MVVM community toolkit with the template generated MAUI app. This toolkit which uses code generators to allow us to create really simple look view model code without all the ceremony…

  • Add the nuget package CommunityToolkit.Mvvm to your references
  • I’m going to store my view models within the ViewModels folder, so add a new folder to your project named ViewModels
  • We’re going to replace the code within MainPage.xaml.cs with our view model, so add a file to ViewModels named MainPageViewModel.cs and it should look like this to start us off
    using CommunityToolkit.Mvvm.ComponentModel;
    
    namespace MauiAppTest.ViewModels;
    
    public partial class MainPageViewModel : ObservableObject
    {
    }
    

    Note: It’s important to make this a partial class, we’ll see why later. The ObservableObject simply gives us the INotifyPropertyChanged and INotifyPropertyChanging implementations.

  • Now within MainPage.xaml.cs, delete the OnCounterClicked method and also delete the line int count = 0;
  • To MainPage.xaml.cs, within the constructor add
    BindingContext = new MainPageViewModel();
    
  • Finally, for now, go to MainPage.xaml and delete the Button’s XAML
    Clicked="OnCounterClicked"
    

At this point we’ve got a bare bones view model which does nothing, so first off we’ll need a property for the count changes and a command which is called to change the count.

  • Within the MainPageViewModel.cs add the following which will create an observable property
    [ObservableProperty] 
    int count;
    
  • Within the MainPage.xaml, change the button’s text to bind to our Count property
    Text="{Binding Count, StringFormat='Click me {0}'}"
    

You might be wondering where the Count property came from, because in our MainPageViewModel.cs with simply declare a field named count (all lowercase and not a property). Well this is the magic of the MVVM toolkit. If you expand the MainPageViewModel.cs in solution explorer you’ll see the class and expanding that you’ll see a Count property, OnCountChanged and OnCountChanging methods where did these come from?

Originally, when we created our view model class, the first important thing is that the class must be a partial class. This allows the next bit of magic, the source generator, to add code to our class without (obviously) altering our class.

When we declare a field using the ObservablePropertyAttribute the MVVM source generator will create the property (with the expected case) along with methods that we could implement for OnXXXChanging and OnXXXChanged. For now let’s look to complete the functionality required to bind the Button to a command and change the Count.

  • Like the ObservableProperty we have another MVVM magical attribute, so add the following code to the MainPageViewModel class
    // you'll need using CommunityToolkit.Mvvm.Input;
    
    [RelayCommand]
    void IncrementCount()
    {
      Count++;
    }
    
  • Now within MainPage.xaml, add the following to the Button XAML
    Command="{Binding IncrementCountCommand}"
    

    Note how the method name is used suffixed with Command when the generator creates our code.

If you try this out, you should see that clicking the button in the UI increments the counter and displays this all via MVVM binding.

We can add code to tell the UI via binding whether the command can be executed by using one of the RelayCommandAttribute’s parameters, CanExecute. Using this we can tell RelayCommand the name of the method to execute, which should return a bool to tell the binding whether we CanExecute the command or now, for example lets add the following to the MainPageViewModel

[ObservableProperty]
bool canIncrement;

bool CanExecuteIncrement() => canIncrement;

and change the existing RelayCommand to

[RelayCommand(CanExecute = nameof(CanExecuteIncrement))]

If you run this now you’ll find that the initial binding of IncrementCountCommand will the CanExecuteIncrement method call returning false and the button will ofcourse be disabled, and we can not enable it at the moment – so let’s just add a simple Checkbox to our MAUI app that binds to CanIncrement, so add before the Button

<CheckBox IsChecked="{Binding CanIncrement}" />

Whilst this will change/toggle the CanIncrement property it will not (as is) tell the binding to essentially re-run the CanExecuteIncrement method. For this to work we just add another attribute to the canIncrement field, making it look like this

[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(IncrementCountCommand))]
bool canIncrement;

The addition of NotifyCanExecuteChangedFor will then call IncrementCountCommand.NotifyCanExecuteChanged() and update the UI accordingly.

Earlier we mentioned that code for the property generates extra methods such as OnXXXChanged. Let’s implement our own OnCanIncrementChanged method. These methods are partial so if we add the following to the MainPageViewModel

partial void OnCanIncrementChanged(bool value)
{
  Debug.WriteLine("OnCanIncrementChanged called");
}

Now, when the property CanIncrement changes, this method is called with the current property value passed as a parameter.

References

MVVM source generators
ObservableProperty attribute
RelayCommand attribute

Adding fonts the a MAUI application

When you create a MAUI application, the default application’s MauiProgram.cs contains the following

builder
  .UseMauiApp<App>()
  .ConfigureFonts(fonts =>
  {
    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
    fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
  });

As can be seen, we’re using .AddFont to add .ttf filename along with an optional alias.

The .ttf files are stored in the Resources/Fonts folder or our application’s project and ofcourse the file name’s match those used in .AddFont

To use our font’s within the MAUI XAML we simply use the alias name like this

<Setter Property="FontFamily" Value="OpenSansRegular"/>

This is taken from the default MAUI application’s Styles.xaml file.

Adding our own font

This all looks fairly simple, so let’s add a font from Google Fonts.

I’m going to download the DynaPuff font, as I want something that will stand out when its changed.

  • Download your font choice
  • From the zip I opened static\DynaPuff and copied DynaPuff-Regular.ttf into my application’s Resources/Fonts folder
  • Within MauiProgram.cs I added the following to the ConfigureFonts method
    fonts.AddFont("DynaPuff-Regular.ttf", "DynaPuff");
    
  • To test this, I changed a XAML Label element (the Hello, World label in the default generated application) to add this
    FontFamily="DynaPuff"
    

And that’s it, really simple.

Removing the Windows 10 search highlights icon

At some point in the upgrades for Windows 10 we ended up with some silly little image on the search text box on the Windows 10 desktop. Turns out this is some form “Search Highlights” functionality. First thing I wanted to do is remove it and whilst I did this on one machine, I just booted my laptop and noticed the stupid thing on this machine, so…

To remove this…

  • Right mouse click on the task bar
  • Select the Search submenu
  • Uncheck the Show search highlights

Hey Swift, how many Range types do you need ?

I was messing around with the random number generator code for Int and noticed that the API has two Range types, Range and ClosedRange. Upon further investigation I found that Swift supports even more range types.

So currently the range types are Range, ClosedRange, PartialRangeFrom, PartialRangeUpTo, PartialRangeThrough and CountableRange.

Range

The Range type is “a half-open interval from a lower bound up to, but not including, an upper bound”. Which basically means the ..< syntax, i.e.

let range = 1..<100

In other words range is from (and including) 1 to 100 (but not including 100).

We might write a function to handle this using the following syntax

// usage rangeTest.range(1..<10)
func range(_ r: Range<Int>) -> Void {
  print("\(r.lowerBound), \(r.upperBound)")
}

ClosedRange

The ClosedRange type is “an interval from a lower bound up to, and including, an upper bound”. Which basically means the … syntax, i.e.

let range = 1...100

In other words range is from (and including) 1 to 100 (and including 100).

We might write a function to handle this using the following syntax

// rangeTest.range(1...10)
func range(_ r: ClosedRange<Int>) -> Void {
  print("\(r.lowerBound), \(r.upperBound)")
}

PartialRangeFrom

The PartialRangeFrom type is “a partial interval extending upward from a lower bound”. Which uses … syntax, i.e.

let range = 0...

We might write a function to handle this using the following syntax

// rangeTest.range(..<10)
func range(_ r: PartialRangeUpTo<Int>) -> Void {
  print("\(r.lowerBound)")
}

PartialRangeUpTo

The PartialRangeUpTo type is “a partial half-open interval up to, but not including, an upper bound”. Which uses ..< syntax, i.e.

let range = ..<100

We might write a function to handle this using the following syntax

// rangeTest.range(..<10)
func range(_ r: PartialRangeUpTo<Int>) -> Void {
  print("\(r.upperBound)")
}

PartialRangeThrough

The PartialRangeThrough type is “a partial interval up to, and including, an upper bound”. Which uses the … syntax, i.e.

let range = ...100

We might write a function to handle this using the following syntax

// rangeTest.range(...10)
func range(_ r: PartialRangeThrough<Int>) -> Void {
  print("\(r.upperBound)")
}

CountableRange

The CountableRange is just a type alias around a Range

Visual Code with vscontainers

Note: It appears in Visual Studio Code 1.73.1 that the process for how to open a container has changed. I’ve added the changes to the post

Visual Code supports vscontainers. Basically a way of running Visual Code, connecting to a docker image and working within that container.

So for example we could run up a Go container with all the Go tooling within it, use Visual Code’s terminal to interact directly with the container and it also support volumes, so allows us to store data directly on our host machine.

If you’re using Windows you’ll need the Docker Desktop and WSL2 installed.

All we need to do is…

Let’s say we wanted to work with a dotnet container. Create a folder to act as your code folder and then create a .vscontainer .devcontainer folder and within that a vscontainer.json devcontainer.json file. Add the following

{
  "image": "mcr.microsoft.com/vscode/devcontainers/dotnet",
  "forwardPorts": [3000]
}

Now use the View | Command Palette (or Ctrl+Shift+P) and run the command >Remote-Containers: Reopen in Container Dev Containers: Reopen in Container. This will restart VS Code and when it’s finished downloading the container image will be ready for you to start interacting with – if you haven’t already got the terminal window open then try opening one. In my case I have a bash terminal. You should now be within the container so just try and run the dotnet CLI command and you should see it’s help/commands.

Obviously if your system already has dotnet installed that probably won’t surprise you or interest you that much, but there’s a bunch of alternative containers, for example, how about a TypeScript Node container

{
  "image": "mcr.microsoft.com/vscode/devcontainers/typescript-node:0-12",
  "extensions": ["dbaeumer.vscode-eslint"],
  "forwardPorts": [3000]
}

To see a list of Microsoft defined containers, take a look at microsoft-vscode-devcontainers.

Here’s another one to try – so I have Swift set up on my Linux server but not on my Windows Box, so using the following will give me a Swift environment

{
  "image": "swift",
  "forwardPorts": [3000]
}

Now from the terminal (as already stated) you’re within the container but you’ll want to store your code on the host machine – well magically works out of the box (so to speak) and I am able to create a folder in the terminal and see it in the host folder I created with .vscontainer within it.

References

Developing inside a Container

.NET HttpClient – the correct way to use it

For ages I’ve been using the HttpClient in .NET without any issues, but usually I have a single endpoint and a singleton (or equivalent) of a class that uses the HttpClient. A while back I needed to call multiple different endpoints using the HttpClient and so I happily wrapped an instantiation of an HttpClient in a using statement, I mean after all it has an IDisposable interface so that makes sense right?

Well NO this is not the case. So don’t do this!

// Don't do this
using(var httpClient = new HttpClient())
{
   // do something with httpClient
}

This post stems from a work colleague pointing me to the post YOU’RE USING HTTPCLIENT WRONG AND IT IS DESTABILIZING YOUR SOFTWARE.

What does the documentation say?

If you take a look at the HttpClient Class documentation states

HttpClient is intended to be instantiated once and re-used throughout the life of an application. Instantiating an HttpClient class for every request will exhaust the number of sockets available under heavy loads. This will result in SocketException errors.

If we take a look at some C# templates in Visual Studio, for example the ASP.NET core Blazor application template, it will give you a scoped instance of the HttpClient, for example

builder.Services.AddScoped(sp => 
  new HttpClient 
    { 
       BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) 
    }
);

So how are we supposed to use a single instance of HttpClient

Let’s now assume that we create an HttpClient per application. Then how do we call multiple service endpoints without having changes affect different endpoint calls and is it threadsafe?

Is the HttpClient thread-safe? Well the answer is both yes and no.

Changing properties on the HttpClient are not threadsafe or at least cannot/should not be modified whilst there are outstanding requests. However methods such as GetAsync, PostAsync, SendAsync etc. are threadsafe which then leads us to how to se set-up different calls, i.e. maybe different headers etc. on all our calls. The answer here is to use SendAsync and create an HttpRequestMessage. This allows us to specify many of the properties we’ll need per HTTP call.

References

YOU’RE USING HTTPCLIENT WRONG AND IT IS DESTABILIZING YOUR SOFTWARE
HTTPCLIENT CREATION AND DISPOSAL INTERNALS: SHOULD I DISPOSE OF HTTPCLIENT?

Nullable reference types in C#

Nullable reference types are now enabled by default on projects created with Visual Studio 2022, so let’s have a quick look at them…

Enabling nullable reference type checking

By default nullable reference types were disabled prior to Visual Studio 2022, so would need enable them at a project or file level. Enabling in the project means adding the following to the .csproj file

<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>net5.0</TargetFramework>
  <Nullable>enable</Nullable>
</PropertyGroup>

If you prefer to enable at a file level then simply add the following to the top of each file

#nullable enable

Now what?

So once you’ve enabled nullable reference type checking, especially if on a legacy code base, be prepared for warnings such as

  • warning CS8625: Cannot convert null literal to non-nullable reference type.
  • warning CS8604: Possible null reference argument for parameter ‘s’ in ‘void Program.SetName(string s)’.
  • warning CS8602: Dereference of a possibly null reference.

I’m sure there are plenty of other warnings, but you get the idea.

Basically what we’re ask the compiler to do is tell us when we might have the potential to be passing a null into a function etc. and highlight the potential issue with a warning. In other words we now need to mark reference types as nullable so the compiler knows we’re expecting a null and in situations where we’re not using a nullable reference type we’ll be warned.

Let’s see some example code. First off, if you default arguments to null, for example

public void SetName(string name = null)
{
   // do something
}

This will result in the warning >warning CS8625: Cannot convert null literal to non-nullable reference type.. All we need to do is tell the compiler we’re expecting a null, by making the argument nullable, i.e. add the ? to the type just like nullable value types.

public void SetName(string? name = null)
{
   // do something
}

Any usage of the variable name will now expect a null check, so if we compile the following

public void SetName(string? name = null)
{
   Console.WriteLine(name.Length);
}

as you’d imagine, the compiler will issue a warning here, in this case warning CS8602: Dereference of a possibly null reference., so obviously we have the potential of a null reference exception here, so adding a conditional check like this will fix that

static void SetName(string? name = null)
{
   if (name != null)
   {
      Console.WriteLine(name.Length);
   }
}

In some situations you may in fact know a variable/argument is not null – in TypeScript it’s not unusual to find the transpiler getting a little confused in which case we use the null-forgiving operator simply an !, so whilst the SetName method, as it stands ofcourse can be null, what if we remove the optional argument and expect all callers of the SetName method – for example maybe it’s a private method and we know each caller must check for null first anyway, then we use the following

static void SetName(string? name)
{
   Console.WriteLine(name!.Length);
}

We’re basically saying, by using name!. we know the value is not null. This example is a little contrived because we could just change the string? to string and not require the !, but you get the idea.