Skip to content

woodcoder/circa

Repository files navigation

Circa - carbon nice scripting

ca., abbreviation for circa (latin), meaning approximately

Circa logo with the abbreviation 'ca.' in a circle

Installation

Download a release and build it using something like the following:

curl -LO https://github.com/woodcoder/circa/releases/download/v0.2/circa-0.2.tar.gz
tar -xf circa-0.2.tar.gz
cd circa-0.2
./configure
make
sudo make install

(You will need to ensure that you have the Curl and Jansson libraries installed. See the Building on... sections below for easy package manager one liners to do this.)

Usage

ca [option ...] timeframe [command [argument ...]]

The ca command will check the Carbon Aware API for the optimal time in the given TIMEFRAME to run the COMMAND to make use of the lowest forecast carbon intensity energy. If no COMMAND is supplied, the program will just block (sleep) until that time.

TIMEFRAME can be given in hours, or a 1d12h30m format.

Circa is a Carbon Hack 22 Project.

Options

-l <location>
specify location to check for carbon intensity
-d <duration>
estimated window of runtime of command/task in hours
-u <sdk url>
url prefix of Carbon Aware API server to consult OR
full path to [Carbon Aware CLI](#carbon-aware-cli) executable

Configuration

Defaults for the url and location settings can be configured system-wide or per user by using a config file. This should be placed in /etc/circa.conf or/and ~/.circa/config. These defaults are overridable by the command line options above.

Architecture

Diagram showing how Circa relates to the Carbon Aware SDK and WattTime data source.

Forecast analytics icon created by photo3idea_studio - Flaticon

Examples

On Linux, you could run the following to pop up a reminder to charge your latop for a couple of hours:

ca -d 2h 8h notify-send "Lower Carbon Energy Available" "Why not plug in your charger?"

On macOS, this does a similar thing:

ca -d 2h 8h osascript -e 'display notification "Why not plug in your charger?" with title "Lower Carbon Energy Available"'

If you install it with WSL under Windows, you can do something similar with this PowerShell script:

function Show-Notification {
    param (
        [string] $ToastText1,
        [string] $ToastText2
    )

    $Notification = "<toast>
      <visual>
        <binding template='ToastText02'>
          <text id='1'>$($ToastText1)</text>
          <text id='2'>$($ToastText2)</text>
        </binding>
      </visual>
    </toast>"

    $null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType=WindowsRuntime]
    $null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data, ContentType=WindowsRuntime]

    $NotificationXml = New-Object Windows.Data.Xml.Dom.XmlDocument
    $NotificationXml.LoadXml($Notification)

    $Toast = [Windows.UI.Notifications.ToastNotification]::new($NotificationXml)
    $Toast.Tag = "Carbon Aware"
    $Toast.Group = "Carbon Aware"
    $Toast.ExpirationTime = [DateTimeOffset]::Now.AddMinutes(1)

    $Notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Carbon Aware")
    $Notifier.Show($Toast);
}

wsl ca -d 2h 8h
Show-Notification "Lower Carbon Energy Available" "Why not plug in your charger?"

Save the above in a file (e.g. carbon-aware.ps1) and run it from a Windows PowerShell prompt. You may need to run Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass in your PowerShell window first.

Screen capture of the windows notification appearing.

Motivation

Inspiration for circa came from thinking about the question "what's the simplest thing that just might work?!".

It would be great to replace cron with a carbon aware version, as there are very many daily jobs that are not time sensitive, and that are just kicked off at midnight, 4am, 6am or similar times because the ops team have to pick a 'quiet' time for them.

However, replacing cron on a system feels like a tricky business. It's a core bit of server infrastructure, so there are trust and security issues.

You'd also need to change the crontab syntax to add in options for a deadline by when you'd like the task to start by and, ideally information about how long it might take to run. To make this backwards compatible would be tricky too.

Hmmm.

So, what about trying to create something that's sort of unix-y, kind of in the composable component philosophy zone? Something a bit nice maybe? Or perhaps in keeping with at and batch? What might that look like?

ca 6h my-cpu-intensive-script.sh

Oh, that looks pretty easy to use!

You could also use it in a shell script around specific commands.

And, maybe, you could use it in a crontab after all:

0 0 * * * /usr/local/bin/ca 6h /path/to/my/daily-report-script.sh

But, hang on a mo - if that took off, then actually, it might provide quite a neat configuration syntax for an carbon aware cron (cacron) too? Like a sort of incremental adoption path where sysadmins could just install ca to time shift one-off tasks. And then, in time, could update cron, which would skip calling ca and just use it as a syntax to inform its own overarching carbon aware schedule.

And that would leave me not having to worry when I schedule my reporting or update checking scripts - I could just let cacron crack on with it whenever the local grid's carbon intensity was at its lowest.

Happy days.

Contributing

Feel free to contact me (woodcoder) on github, taikai or discord.

Building on macOS

Intel

brew install pkg-config autoconf automake libtool libcurl jansson
autoreconf -fi -I /usr/local/opt/curl/share/aclocal
./configure
make

Apple Silicon

brew install pkg-config autoconf automake libtool curl jansson
export CPATH=/opt/homebrew/include
export LIBRARY_PATH=/opt/homebrew/lib
autoreconf -fi -I /opt/homebrew/opt/curl/share/aclocal
./configure
make

Building on Ubuntu

sudo apt-get install -y build-essential libcurl4-openssl-dev libjansson-dev
autoreconf -fi
./configure
make

Building on Fedora

sudo dnf -y install autoconf automake curl-devel jansson-devel
autoreconf -fi
./configure
make

Building on Manjaro

sudo pacman -S base-devel curl jansson
autoreconf -fi
./configure
make

Carbon Aware CLI

To install the SDK CLI you will first need the .NET SDK

  • macOS - download and install the macOS .NET SDK Installer.
  • Ubuntu - sudo apt-get install -y dotnet-sdk-6.0
  • Fedora - sudo dnf -y install dotnet
  • Manjaro - sudo pacman -S dotnet-sdk aspnet-runtime

Then you will need at least version 1.0.1 or later

curl -LO https://github.com/Green-Software-Foundation/carbon-aware-sdk/archive/refs/heads/dev.tar.gz
tar xf dev.tar.gz
cd carbon-aware-sdk-dev/src/CarbonAware.CLI/src

Update the appsettings.json, for example, with your WattTime credentials:

vi appsettings.json 
{
    "Logging": {
      "LogLevel": {
        "Default": "Information",
        "Microsoft.AspNetCore": "Warning"
      }
    },
    "AllowedHosts": "*",
    "DataSources": {
      "EmissionsDataSource": "WattTime",
      "ForecastDataSource": "WattTime",
      "Configurations": {
        "WattTime": {
          "Type": "WattTime",
          "Username": "<watttime username>",
          "Password": "<watttime password>",
          "BaseURL": "https://api2.watttime.org/v2/"
        }
      }
    }
}

Build a release and test it:

dotnet publish -c Release
bin/Release/net6.0/publish/caw emissions -l eastus

Troubleshooting

You can check your WattTime credentials directly using the below:

curl https://api2.watttime.org/v2/login -u '<watttime username>:<watttime password>'

Choosing the westus location sometimes works if your plan is restricted.