Buy me a cup of coffee 

Software development is powered by coffee... if you use any of our open source pojects, it would make my day if you'd buy me a cup (or several). Just click on the coffee cup.

Reactive Communications for ASCOM Version Update 0.5.1

Tags: ASCOM, astronomy, open-source, software, free software, free, software-engineering, software engineering, reactive-extensions

Reactive ASCOM

I have pushed a new version 0.5.1 of the Reactive Communications Library for ASCOM to NuGet Gallery and the source code to BitBucket.

This release introduces a new class called ChannelFactory. Previously, users were responsible for creating and managing connection strings, device endpoints and channels. It was possible to create and use custom channel implementations but the library code was not really very well factored for supporting this.

Now, the user needs only a connection string. A channel can then be obtained by calling ChannelFactory.FromConnectionString().

By default, ChannelFactory knows how to create the builtin channel types, which currently is only serial port channels. In the future, more builtin channel types may be added, but for now users can add their own custom channel implementations by calling ChannelFactory.RegisterChannelType(). This call takes three delegates:

  • A Predicate<string> that tests whether a connection string is valid for the channel type and returns true if it is.

  • A Func<string, DeviceEndpoint> that takes a valid connection string and returns an object derived from DeviceEndpoint appropriate for the channel type.

  • A Func<DeviceEndpoint, ICommunicationsChannel> that takes a valid endpoint and creates the channel.

    As an example, say a particular project uses a hardware simulator within its unit tests and we wish to create a SimulatorCommunicationsChannel that communicates directly with the simulator in memory. Connection strings for the simulator will be in the form:

    "Simulator" [: ("Fast" | "Realtime")]

So valid connection strings will be: "Simulator", "Simulator:Fast", "Simulator:Realtime"

We will create a class SimulatorCommunicationsChannel and a supporting class SimulatorEndpoint derived from DeviceEndpoint to describe our simulator connection. The endpoint class is a good place to put any static builder methods that we'll need to construct the channel (for example, here we've included FromConnectionString() and IsConnectionStringValid().

internal class SimulatorEndpoint : DeviceEndpoint
    const string realtime = "Realtime";
    const string fast = "Fast";
    string connectionString;
    const string connectionPattern = @"^Simulator(:(?<Speed>(Realtime)|(Fast)))?$";
    static readonly Regex connectionRegex = new Regex(connectionPattern, Options);

    public static SimulatorEndpoint FromConnectionString(string connection)
        if (!IsConnectionStringValid(connection))
            throw new ArgumentException($"Invalid connection string: {connection}");
        var matches = connectionRegex.Match(connection);
        var speed = CaptureGroupOrDefault(matches, "Speed", "Fast");
        var timing = speed.Equals(realtime, StringComparison.InvariantCultureIgnoreCase);
        return new SimulatorEndpoint(connection) {Realtime = timing};

    public static bool IsConnectionStringValid(string connection)
        return connectionRegex.IsMatch(connection);

    SimulatorEndpoint(string connectionString)
        this.connectionString = connectionString;

    public bool Realtime { get; set; }

    public override string ToString()
        return $"Simulator:{(Realtime ? realtime : fast)}";

Note that the endpoint class includes all of the helpers needed to register our new channel type. So in test code, we can register our new channel type thus:

var channelFactory = new ChannelFactory();
    endpoint => new SimulatorCommunicationsChannel(endpoint as SimulatorEndpoint)

We can then create a channel as simply as this:

var channel = channelFactory.FromConnectionString("Simulator:Fast");

Let Us Know What You Create

If any users develop custom channel implementations then we'd be delighted to hear about it. Please drop us a line and let us know. If you create something generally useful (e.g. an Ethernet channel or a USB channel) then if you are willing, we could collaborate on adding it to the library as a builtin channel type.

We'd also like to know if you create an ASCOM driver or other piece of communications software using the Reactive Communications library. It is hard to know whether anyone is actually using the project apart from us. If we hear people are using it, we are much more likely to actively engage in maintaining and improving the code.

And finally, our open source projects are always available for free without obligation of any kind. If we helped you and you'd like to give something back, then please consider buying us a few cups of coffee, which you can do from the bottom of any page on the Tigra Astronomy web site by clicking on the coffee cup icon. Give a lot, give a little or give nothing at all, and enjoy the software.

No Comments

Add a Comment

TeamCity Build Status

Let Us Help You

Find us on Facebook