bmc::labs was born from freelance engagements and as such, we still do most of our software engineering work on customer projects. As is often the case, we are not at liberty to discuss the details of our assignments - so in this article, we’d like to give an impression of, and a small peek into, our software engineering work.

tiny projects

During our ongoing assignments, a lot of code gets prototyped in command line applications and prototypes. Sometimes we find ourselves missing simple utilities that really shouldn’t be missing, and we create them ourselves. A lot of the time, they don’t find their way onto the web, but sometimes they do - like our C++ progress bar did.

What we needed was something like this:

[----->                             ]  10% -  0:42.312 elapsed

Ideally, it would have a modern C++ interface and work on all platforms. In other words: code should look as follows on Windows, macOS and Linux alike.

bmc::progress_bar pb{
  13,    // min, also initial value
  156,   // max
  80,    // width in percent of screen
  true,  // auto increment when outputting
  true   // show time at the end
};

// generate some data to have something to iterate
std::vector<int> vec(pb.size());
std::iota(std::begin(vec), std::end(vec), 42);

for (auto & e : vec) {
  e *= 2;  // suppress unused variable warning
  std::this_thread::sleep_for(50ms);
  std::cout << pb;
}

And indeed, it does work. The code is on GitHub as previously linked. It’s a clone of our internal GitLab repo so you’ll have to trust us that the pipeline status says “passed”, but it works.

There are more of these and we hope to make them available as we go. It’s mostly about finding the time and muse to prepare something cleanly and properly, even if it’s tiny, and there is usually a long list of things on our to do lists.

automated data processing

One of our long-time projects is data engineering and software systems consulting for WSC Group, the owner of the TCR brand and technical regulations. Part of our responsibilities there is monitoring regulation conformance of cars. That is: the data logged in the dedicated data loggers of TCR cars can contain indicators for the violation of technical regulations. One such parameter is turbocharger boost pressure. The boost pressure allowance is certified per model of car and then must be checked against the given limit.

If all of that went over your head, consider this fictional, yet representative data:

Fig. 1: Plot of various parameters in aracecar Fig. 1: Plot of various parameters in a racecar

The blue line is a pressure, and for this pressure exists table how high it may be at which RPM (the green line). We were asked to work on (a) strategies to filter and monitor data and (b) software to do so easily, i.e. to enable users who are not Python- or MATLAB®-savvy.

We produced a multiplatform Qt application in C++ which is capable of checking entire sets of logged data and plotting turbocharger boost pressure versus RPM (this way of visualizing the data was a customer request). It is called GridBoxLite and looks like this:

Fig. 2: Screenshot of GridBoxLite Fig. 2: Screenshot of GridBoxLite

You’ll notice a lot is blurred out, and I apologize. The data shown is not fictional, but not from a point relevant session either, but we aren’t comfortable showing it without blur nonetheless.

sneak preview

Finally, we are currently working on a data management solution for Balance of Performance data gathered in testing, simulation and on track. The front end of this application will run in the browser, with a back end written in Rust to enable efficient on-the-fly data interfacing (and of course, because we know Rust and love it to death). We probably won’t ever be able to do a detailed write-up of what the application is going to be doing, but I absolutely wanted to start showing more code on this blog, so here goes - why Rust is awesome.

For this project, we wanted a simple error type. Something easy to use and capable of - for now - only error messages, no contexts, no backtracing, no nothing. So after playing a bit with the crates snafu and failure (and admittedly before finding the anyhow, which looks very cool) we rolled our own:

pub struct Fubar(pub String);

impl Fubar {
  pub fn new(msg: &str) -> Self {
    Self(msg.to_string())
  }
}

impl fmt::Display for Fubar {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "{}", self.0)
  }
}

impl error::Error for Fubar {}

Again, for now we don’t need any other functionality beyond error messages. When we do, we’ll build in backtracing and such. Or we’ll have a look at anywhere… ;)

This error of course needs a result type to go with it:

pub type Result<T> = result::Result<T, Fubar>;

But how do we use that everywhere and using the ? operator? Well, we need to implement the From trait for every error type we want to be able to convert from. But that would look the same for all the error types, it would be a copy-paste-exercise, and that goes against our inner DRY voice. So, let’s do it via macro and immediately call that macro with all our desired error types:

macro_rules! implement_from {
  ($($ErrType:ty),*) => {$(
    impl From<$ErrType> for Fubar {
      fn from(error: $ErrType) -> Self {
        Self(error.to_string())
      }
    }
  )*}
}

implement_from!(std::io::Error,
                docopt::Error,
                git2::Error,
                json::Error,
                mongodb::error::Error,
                toml::de::Error,
                toml::ser::Error);

É voilà! If any additional error types are needed, we simply add them to the list and we can use our result type everywhere, throughout the code base.

There are some other macros to our error type. If we don’t happen to switch to anyhow, I am probably going to cover them in a future blog post.

Also, I’m aware that this is maybe not the best and most fully-fledged error type implementation ever. It is beautiful, though, as Rust tends to be, so I found it a good example for a sneak preview. Hope you enjoyed it!

final words

If you are still reading, I sincerely hope I was able to provide a very rough overview of what we do. There is of course a lot more - prototyping in Python and MATLAB®, front end logic in JavaScript and TypeScript, and I’ve omitted embedded software from this article entirely - but that is for another post.

We are committed to FOSS whenever we can and we would like to contribute much more than we do. We hope to change this in the future, especially in the embedded systems realm. Until then, stay healthy.

we.are.#baremetal