The place where random ideas get written down and lost in time.

2022-05-11 - Google I/O 2022

Category DEV

Things to try:

  • Jetpack Compose for Android UI (e.g. Timer app)
  • Flutter 3
  • Google Cloud Run as an alternative to Amazon w/ React

Nerdkill could be a good subject to try the latest “Flutter 3 Casual Game Kit” thingy.


2022-05-10 - Arduino Sequence Controller?

Category DEV

I’ve been thinking about how Lacan uses his Arduino for his aircraft animation.

What he needs is really a sequence controller to create time-base sequences triggered by input events.

If I had to program this from scratch, what would I do? I’d create a “mini language” using either macro or C++ objects which represents states to change over time:

  • LED timings is really just a list of (start timestamp, LED pin, LED state).
  • Servos: (start timestamp, servo pin, angle to reach, speed or duration)
  • Motors: (start timestamp, motor pin, power level, direction)
  • Instructions to end sequence, repeat N times, or chain to another sequence.

Depending on the specific needs:

  • Sequence(s) are started by an input (with either forced restart or don’t retrigger).
  • Need more than one concurrent sequence? Make each sequence independent. That is each sequence is started and actuates by itself on main clock.
  • Need to make sequences run solo? Have an instruction that stop/cancel all other sequences.
  • Maybe put sequences in groups (e.g. “servo groups”, “lights groups”) and make the group exclusive as in only 1 sequence runs in the group, or be able to stop any running sequence in the group.

For example for the case of the variable geometry plane:

  • IR button 1 ⇒ sequence 1 = stop sequence 2, move servo N up to 60. No retrigger.
  • IR button 2 ⇒ sequence 2 = stop sequence 1, move servo N down to 0. No retrigger.
  • IR button N ⇒ sequence N for lights.

It seems so obvious that I would be surprised if this had not been done before and be made available as a customizable library for arduino.

For model trains, there are a couple obvious usages:

  • Sequencing road traffic lights, e.g. to animate a city.
  • With the addition of a “random LED value” instruction, animate anything from a camp fire to a building in fire.


2022-02-20 - Cat Litter Box Timer

Category DEV

Where’s the source for the current “Timer” app used for the litter box?

Device it uses: Tmo (saffire?) 3g something… running Android 2.2 (aka Froyo).

API level ⇒ API 8

As an exercise, it would be nice to rewrite this in Kotlin to see if it can run on Froyo. (FAQ says there’s no min sdk req).


2021-12-25 - Conductor 2

Category DEV

It's time to reflect on Conductor 2 again.

The repo branch has been going nowhere lately. I moved the project to a new repo (in the randall-layout workspace) and only copied the conductor 1 part. That made me realize I'd be throwing away a valuable part with the SVG map.

So first I want to salvage that part. The UI is and should be separated from the engine. This UI was going to drive a simulator, and I can likely make that happen on top of conductor 1.

The next part I want is to formalize the spec for conductor 2. Forget the syntax for now, I need to get the requirements right first: block handling, route management, and fully convert a current script. Also write some examples for eg window block handling.

(Reading between the lines, what I’m saying is that the Conductor-2-with-Groovy-DSL shows me that in fact I want more profound changes than “just a DSL”. I really want to rethink the entire way the automation scripting is done.)

Then once we have that we can figure the implementation. Maybe getting entrenched in groovy is not helpful here. There's clearly some value in not writing my own language, unless it slows me down.

The discussion continues in the Conductor 2 doc.


2021-12-19 - Status of Conductor 2

Category DEV

I haven’t written one so it’s worth explaining the status of Conductor 2:

  • Entirely rewrote the current v44 script using an “enhanced” version of Conductor 1 syntax to explore a realistic way to describe and use the new routes concept.
  • Considered whether it’s worth pursuing the Groovy DSL vs extending the Conductor 1 DSL…
    • The decision is that the former Conductor 2 Groovy DSL is obsolete. It was premature. Part of the issue was that it was getting entrenched in bridging the functionality and implementation (at the same time) with the former Conductor 1 engine. That is not the proper way to prototype.
    • Instead, modularized the Conductor 1 source code to move the engine/DSL into a sub-project.
    • And added a mock Conductor Groovy DSL rewritten from scratch, focusing on how the syntax would work rather than the actual implementation. There are unit tests but they only validate that the DSL can actually encode what it’s supposed to.
    • The goal is to later also do a mock Kotlin DSL and compare.
  • I still need to create a fat jar where this is invoked as Jython add-on from JMRI, to ensure there’s no library mismatch for example when running Groovy or Kotlin runtime code.
  • That led me to explore the fundamental issue with the current route system, namely that we must have “managers”, “active routes”, and the sequence/shuttle manager should deal with a node graph instead of a “block list”. After much back-and-forth debate, I think I finally have a system I can endorse. Now I must encode it using the Groovy DSL.


2021-11-11 - “nvm” for Multiple Node Versions

Category DEV

Right now on the laptop for RPisicine I have:

$ node --version        ⇒ v14.11.0

$ npm --version        ⇒ 6.14.8

https://github.com/nvm-sh/nvm

⇒ install.sh

$ nvm list                # takes a while...

Install steps recommend to remove “-g” (global) modules that will likely break when changing version globally:

$ nvm use system

$ npm uninstall -g nwb

$ npm uninstall -g serve

$ nvm install v14.11.0

In rpiscine:

$ node --version > .nvmrc

$ nvm use        # in that directory, to switch to that version

How does changing the Node version with nvm affect the NPM version?

⇒ The NPM version depends (and varies with) the Node version being used. E.g.:

$ nvm use node

Now using node v14.11.0 (npm v6.14.8)

$ nvm install node

Now using node v17.1.0 (npm v8.1.2)

For Windows, there’s https://github.com/coreybutler/nvm-windows

To fix the NVM PATH in CMD.exe: Not really an option when installed using nvm-sh since the latter does not create an “nvm.exe” or “nvm.sh” -- instead all the nvm commands are bash functions loaded in the interpreter (meh). But we can work around it:

  • cygwin: $ cygpath -w $(dirname $(nvm which --silent))
    • ⇒ C:\$USER\.nvm\versions\node\v18.8.0\bin
    • Copy path to a CMD.exe.
  • cmd:         > refreshenv                ← optional, because I have chocolatey installed.
    • > set PATH=C:\%USER%\.nvm\versions\node\v18.8.0\bin;%PATH%
    • > echo %PATH%


2021-10-11 - RPiscine project

Category DEV

An update on Projet RPiscine aka Piscine 2:

  • Python service: access RPi PiFace, store data, expose data via REST JSON.
  • React JS served via nginx to connect to the Python service + visualize the data.

This worked very well. The “backend vs frontend” split was good.

The setup allows for a local react dev on laptop, build on laptop, then push the build site to the RPi.

This runs on an RPi 1 B (the older kind), with Debian buster, and using systemctl services for the python wrapper. Also a reverse-ssh service wrapper is created, which works very nicely. Using the new systemctl service is a nice improvement over the old initd scripts.


2021-09-09 - Feature flag based Android app

Category DEV

What would it take to do an Android app that is modular and where each feature is controlled by a remote server feature flag?

Would I choose something like Firebase, AWS, or a custom server like Alfray or RDRR?

The data itself would likely be json or proto. We would want to have version capabilities.

Notions that become relevant are cold vs hot config, refresh times, networks caching. Also an ETag / checksum system could be used to only send diff/update and minimize network traffic.


2021-09-03 - End of Summer Project B3

Category DEV

Time to end the summer project with Bearing B3. Steps needed:

  • Publish it!
  • Check if I can update only the Installed version, without the “Instant” one.
  • I do realize the Installed-vs-Instant doesn't make a lot of sense in this case due to the preference storage for the Waypoints list. When updating, any waypoints created with the Instant one will be lost.

Either way I’m likely to remove the Instant version as it’s mostly pointless here. It’s only here as an exercise...


2021-08-28 - Train Motion: FatJar vs ClassPath?

Category DEV

In the Train-Motion project, I have a fat jar gradle rule to package all the dependencies in a single jar.

To make it work, I had to create a “configuration” in gradle:

configurations {

    runtimeCompile {

        canBeResolved = true

        canBeConsumed = true

    }

    compileClasspath.extendsFrom(runtimeCompile)

    runtimeClasspath.extendsFrom(runtimeCompile)

    testCompileClasspath.extendsFrom(runtimeCompile)

    testRuntimeClasspath.extendsFrom(runtimeCompile)

}

Then I use this configuration to include the dependencies:

dependencies {

    runtimeCompile project(":LibUtilsJava")

    runtimeCompile "commons-cli:commons-cli:1.4"

    runtimeCompile "org.bytedeco:javacv-platform:1.5.3"

    runtimeCompile "org.bytedeco:javacpp-platform:1.5.3"

    runtimeCompile "uk.co.caprica:vlcj:4.7.1"

    runtimeCompile "com.fasterxml.jackson.core:jackson-databind:2.10.2"

    runtimeCompile "com.squareup.okhttp3:okhttp:3.10.0"

    runtimeCompile "org.eclipse.jetty:jetty-server:9.4.29.v20200521"

    runtimeCompile "com.google.dagger:dagger:2.28"

    runtimeCompile  "com.google.auto.factory:auto-factory:1.0.1"

}

And finally a fatJar task collects these specific dependencies and packages them together:

task fatJar(type: Jar) {

    manifest.from jar.manifest

    classifier = "all"

    from {

        configurations.compileClasspath.collect { it.isDirectory() ? it : zipTree(it) }

    } {

        exclude "META-INF/*.SF"

        exclude "META-INF/*.DSA"

        exclude "META-INF/*.RSA"

    }

    with jar

}

Note that “runtimeCompile” is a superset of the “compile” configuration, and the artifacts can be found using configurations.compileClasspath.

That’s neat to create the needed single JAR. That jar is ~760 MB with all the OpenCV deps. And it takes an interminable 4 minutes to create the jar itself.

So now the question is whether I can avoid that. I don’t need to distribute the jar, so I'd be fine with crafting a specific command line with the needed classpath. Or even having a “gradle run” task that does not need the fat jar first.


  Generated on 2025-10-07 by Rig4j 0.1-Exp-f3ee0b3