The place where random ideas get written down and lost in time.
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:\Ralf\.nvm\versions\node\v18.8.0\bin
- Copy path to a CMD.exe.
- cmd: $ refreshenv ← optional, because I have chocolatey installed.
- $ set PATH=C:\Ralf\.nvm\versions\node\v18.8.0\bin;%PATH%
- $ echo %PATH%
2021-10-11 - RPiscine project
Category DEVAn 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.
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 DEVTime 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...
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.
2021-08-18 - Bearing B3 Features
Category DEVNow that we have a basic “marked locations” list in B3, it’s time to review the UI and adjust.
The goal was to do it in Kotlin, and that’s been done.
One issue was the “Marked Locations” wording, which seems problematic. Isn’t there something better… “waypoints” seem like a better name.
So let’s do a few changes:
- Vocabulary:
- A “Location” is just a raw GPS location coordinate (latitude + longitude).
- A “Waypoint” is a location coordinate combined with a name.
- Screen “Marked Locations” ⇒ “Waypoints”
- “Marked Location” ⇒ “Selected Waypoint”
- “Location N” ⇒ “Waypoint N”
- Rename class Mark to Waypoint / Waypoints / WaypointsAdapter.
- Screen “Compass”
- “Marked Location” ⇒ “Target Location”
- (that should make it more obvious it’s the target of the bearing)
- Menu Recall / Edit ⇒ keep as-is for now.
We’ll keep the wording as “Location” (Target vs GPS) in the Compass screen.
I feel like a case of deja vu so I need to write this down.
- Robolectric: simulating an Android runtime working on top of the JVM, local dev machine. No emulator needed.
- Used to be simple and straightforward. Since Robolectric 4 and recent android gradle updates, some things have been deprecated / changed making it harder to use.
- AndroidX runner “AndroidJUnitRunner” tests which go in androidTest folder: run on device or emulator, and are essentially the modern version of the instrumentation tests.
- Setup for gradle imports is highly modular. For ref:
- https://developer.android.com/training/testing/set-up-project
- AndroidX runner “AndroidJUnit4” tests which go in androidTest folder: run on device or emulator too ⇒ the test folder name indicates which build rule is used and where the test runs.
- AndroidX runner “MockitoJUnitRunner” tests which go in the test folder: run on JVM.
- This is provided by mockito-core and is basically a JUnit runner that also happens to auto-init all the @Mock instances. ⇒ Just a convenience over the usual Mock rule, no relation to Android framework.
- How much of the Android framework can be used with that? ⇒ none
- Robolectric with AndroidX tests:
- http://robolectric.org/androidx_test/
- Use the “AndroidJUnit4” runner.
- Confusing because nothing makes it clear these are Robolectric tests.
What I have done for Cab v2:
- Build.gradle > defaultConfig > testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- ServersActivityTest:
- @RunWith(AndroidJUnit4.class)
@Config(application = TestMainApp.class)
ApplicationProvider.getApplicationContext()
ActivityScenario.launch(MainActivity.class) - The cabv2 TestMainApp derives from the LegacyMainApp and replaces the IAppComponent by the ITestAppComponent for testing. That’s how test modules are injected in the app.
Since updating B3, I was getting errors:
- “robolectric RuntimeException Method not mocked”
- They are “solved” by adding this to app gradle:
- testOptions > unitTests > returnDefaultValues = true
- Which in turn creates another error: “java.lang.ClassNotFoundException: android.content.res.ApkAssets”
- Real solution: following https://github.com/robolectric/robolectric/issues/4740
- The dumb solution is to remove the m2 robolectric cache so that it gets downloaded again.
This explains:
- How to use an offline version of the Gradle wrapper.
- How to use an offline version of a project’s Maven repo dependencies (cached once).
Kotlin / rig4k is a good potential idea but really a project based around GDoc downloads & APIs sounds like a painful thing to do in PA. It requires internet connection (duh). But also GDoc APIs are notorious to change each time I look at them, requiring even more research -- that is there’s the issue that I’d have to learn the “idiomatic kotlin” and the “idiomatic gdoc API” at the same time.
So instead, what about Bearing? It could be a good Kotlin candidate:
- No new API learning curve. The usual Android stuff, just done as Kotlin.
- Can focus on Kotlin syntax & such.
- One option would be to rewrite the whole app in Kotlin, however… what’s the benefit?
- Can just mix with the current version and add new stuff in Kotlin.
That is the addition would be a new fragment or activity for a mark list management, which is neatly self-contained.
When I (re)created Bearing B3, I tried a few things:
- The “new” ABB (Android Bundle) mode.
- Not a big fan but this is the way to go since Play will eventually make AAB mandatory in 2021 or 2022.
- It was a good test and useful, and I shall keep it that way for distrib.
- The new “instant vs installed” modes.
- That was good learning to realize that instant creates some limitations, e.g. can’t bundle analytics stats with it.
- Other than that, it makes the build config a bit more complicated by having 2 variants.
- Overall it doesn’t bring much in terms of visibility. E.g. how many apps are installed vs run as instant?
- FirebaseAnalytics instead of GA.
- Same difference?
- Need to constantly update the library… it’s obsolete again IIRC.
Work suggestions:
- Remove the “instant” variant. Only keep the installed one.
- What about google play? Can I remove the instant version there too?
- ⇒ update the “installed” version first and check if the “instant” can be removed from Play. If it does, then cleanup the “instant” build script + code.
- Check updating of the Firebase library.
- ⇒ That’s enough update needed to create the new installed variant.