• Converting your Gradle build files to the Kotlin DSL

    Ever wanted to customize your Android build workflow and found yourself limited by your knowledge of Gradle’s historical configuration language, Groovy?

    Well, I have good news for you: for a while now, Gradle has supported Kotlin as a first-class language. Chances are if you’re an Android developer and you’re reading this, you probably already know Kotlin pretty well (and if not, it’s not too late)!

    Converting an existing project to the Kotlin DSL can be a bit of a pain if you don’t know where to start. This article will try to guide you through the process.

    Before we start

    Try to start from a clean state, with a recent version of Gradle, Android Studio, and your build plugins. This is good practice anyway and might prevent some unfortunate incompatibilities.

    Be sure to keep some documentation on hand in case you need it:

    Use the plugins block

    If you’re still importing your Gradle plugins using the apply syntax, you should start by migrating to the plugins block. This has been the recommended practice for a while.

    Instead of:

    apply plugin: 'com.example.hello'
    

    Do this:

    plugins {
        id 'com.example.hello'
    }
    

    You can also specify the plugin’s version, if it’s third-party.

    plugins {
        id 'com.example.hello' version '1.0.0'
    }
    

    Read more about the plugin DSL in the Gradle docs.

    Convert your Gradle files

    A great fact about the Kotlin DSL is that you’re not required to migrate everything at once, just like you didn’t have to convert your whole Java app to Kotlin at once. It works on a file-by-file basis. Especially great if you have many modules!

    Start by renaming one of your build.gradle files to build.gradle.kts. Everything should break. Gradle doesn’t know how to build anything yet and freaks out a little; don’t worry, it’s fine. 👍

    Some common syntax changes

    Before getting deeper into some specific DSL changes, you can apply a first pass on your build files to fix most syntax issues.

    Single-quoted strings should be converted to double-quoted strings.

    A simple search-and-replace is usually good enough.

    Instead of:

    'proguard-android-optimize.txt'
    

    Do this:

    "proguard-android-optimize.txt"
    

    Function calls add parentheses and equal signs for named parameters

    This can vary a little depending on the API, but generally looks like this.

    Instead of:

    apply from: 'shared.gradle'
    
    maven { url 'https://jitpack.io' }
    

    Do this:

    apply(from = "shared.gradle")
    
    maven(url = "https://jitpack.io")
    

    Kotlin plugins can be declared with a handy kotlin() function

    Instead of:

    plugins {
        id 'com.android.library'
        id 'kotlin-android-extensions'
    }
    

    Do this:

    plugins {
        id("com.android.library")
        kotlin("android.extensions")
    }
    

    Array declarations can be declared with listOf()

    Instead of:

    freeCompilerArgs = [
        "-Xallow-result-return-type", 
        "-Xuse-experimental=kotlin.Experimental"
    ]
    

    Do this:

    freeCompilerArgs = listOf(
        "-Xallow-result-return-type", 
        "-Xuse-experimental=kotlin.Experimental"
    )
    

    Some boolean properties have been renamed

    Instead of:

    minifyEnabled true
    

    Do this:

    isMinifyEnabled = false
    

    Referencing specific build types

    Since the Kotlin DSL doesn’t know about dynamically generated build types, you can’t write this directly in Kotlin:

    buildTypes {
        release {
            minifyEnabled false
        }
    }
    

    Instead, refer to a build type with named():

    buildTypes {
        named("release") {
            isMinifyEnabled = false
        }
    }
    

    What about properties?

    If you have more than a simple project, you probably use project properties to define your versions and dependencies in a centralized way.

    Let’s pretend you have this shared.gradle file:

    ext {
        min_sdk_version = 21
    }
    

    In Groovy, you could access these properties by importing the file (probably in your buildscript {}):

    apply from: 'dependencies.gradle'
    

    …and simply referencing them from your project file.

    defaultConfig {
        minSdkVersion min_sdk_version
        targetSdkVersion 30
        versionCode 1
        versionName "1.0.0"
    }
    

    With the Kotlin DSL, these properties can be declared and delegated to extra in a fairly easy way.

    val target_sdk_version: String by ext
    
    android {
        compileSdkVersion = target_sdk_version
        ...
    }
    

    You can also use the map syntax if you need to.

    android {
        compileSdkVersion = ext["target_sdk_version"] as String
        ...
    }
    

    Properties aren’t especially the best tool once your whole project uses the Kotlin DSL; however, it could be useful to be able to access them in the meantime.

    Taking advantage of Kotlin

    Once your project uses the Kotlin DSL, you can use its full power by creating a buildSrc module.

    Creating the module

    In your project’s root directory, create a new buildSrc module with a single build.gradle.kts file.

    It should look like this:

    plugins {
        `kotlin-dsl`
    }
    
    repositories {
        jcenter()
    }
    

    Set up the usual src/main/kotlin source tree and sync your project. You can write regular Kotlin code here, and it will be available as-is in your build scripts!

    Managing dependencies in Kotlin

    This section is all a suggestion; as far as I know, there is no clear guidance on how you should declare and manage your project’s dependencies, so you might want to have a different approach with your project. But the great thing about the Kotlin DSL is that it’s super flexible!

    In the case of my application, here’s what a module’s dependencies used to look like:

    dependencies {
        implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
    
        implementation "androidx.core:core-ktx:$androidx_core_version"
        implementation "androidx.appcompat:appcompat:$androidx_appcompat_version"
    
        implementation "androidx.room:room-runtime:$kotlinx_room_version"
    
        // Network libs
        implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
        implementation "com.squareup.moshi:moshi:$moshi_version"
        kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
    
        // Testing
        testImplementation "org.junit.jupiter:junit-jupiter:$junit_version"
        testImplementation "org.mockito:mockito-core:$mockito_version"
    }
    

    Now they look like this:

    dependencies {
        // Kotlin runtime
        implementation(Dependencies.Kotlin.stdlib)
    
        implementation(Dependencies.AndroidX.core)
        implementation(Dependencies.AndroidX.appcompat)
    
        implementation(Dependencies.AndroidX.Room.common)
    
        // Network libs
        implementation(Dependencies.Retrofit.core)
        implementation(Dependencies.Moshi.core)
        kapt(Dependencies.Moshi.codegen)
    
        // Testing
        testImplementation(Dependencies.Test.junit)
        testImplementation(Dependencies.Test.mockito)
    }
    

    I achieved this by creating a Dependencies.kt file in buildSrc:

    object Dependencies {
    
        object AndroidX {
            const val appcompat = "androidx.appcompat:appcompat:1.3.0-alpha01"
            const val core = "androidx.core:core-ktx:1.3.0"
    
            object Room {
                private const val version = "2.2.5"
                const val common = "androidx.room:room-ktx:$version"
                const val compiler = "androidx.room:room-compiler:$version"
            }
        }
    
        object Kotlin {
            private const val version = "1.3.72"
            const val stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$version"
            const val plugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:$version"
        }
    
        object Moshi {
            private const val version = "1.9.2"
            const val core = "com.squareup.moshi:moshi:$version"
            const val codegen = "com.squareup.moshi:moshi-kotlin-codegen:$version"
        }
    
        object Retrofit {
            private const val version = "2.8.1"
            const val core = "com.squareup.retrofit2:retrofit:$version"
            const val moshiConverter = "com.squareup.retrofit2:converter-moshi:$version"
        }
    
        object Test {
            const val junit = "org.junit.jupiter:junit-jupiter:5.6.0"
            const val mockito = "org.mockito:mockito-core:3.2.4"
        }
    }
    

    This makes it super easy to refactor and see which dependency is used by which module, as well as upgrade their versions and keep them in sync.

    This method can be extended to manage your build dependencies and their versions, as well as things like app version numbers. You can of course use the Kotlin stdlib to add any needed logic as functions as needed.

    Conclusion

    Migrating my personal project to the Gradle Kotlin DSL was not the easiest thing. The lack of conversion tools and succint guides or documentation makes it a bit hard to get into, especially for users who might not already be super familiar with Groovy.

    However, with some time to convert each file and some help from sample projects, it’s not the hardest task either! The migration can be gradual and brings real advantages, especially for Kotlin lovers. Understanding, extending and optimizing my build system is now easier than ever.

    Bye bye, Groovy. 👋

  • Intégrer SmartHab à la solution domotique Home Assistant

    Home Assistant propose une solution logicielle de “box” domotique open-source qui s’installe sur n’importe quel matériel (par exemple un Raspberry Pi) et propose de nombreuses intégrations avec des appareils connectés.

    Si vous vivez dans un logement équipé de la solution de domotique de SmartHab, vous cherchez peut-être un moyen de l’intégrer avec le reste de votre équipement via un logiciel comme Home Assistant. Moi aussi ! C’est pourquoi j’ai développé un plugin SmartHab pour Home Assistant.

    home-assistant smarthab overview

    Une fois mise en place, l’intégration vous donnera accès à toutes les possibilités de Home Assistant : automatisation, contrôle depuis iOS via HomeKit, contrôle vocal depuis Alexa ou Google Home…

    Soyez prévenu·e : Home Assistant n’est pas un logiciel facile à prendre en main, et un certain niveau en anglais et en configuration textuelle de logiciels vous sera plus qu’utile.

    Une fois le composant SmartHab publié (vous pouvez consulter la liste des composants actuellement disponibles), il suffira d’installer Home Assistant et d’ajouter ces lignes dans le fichier configuration.yaml :

    smarthab:
      email: john.doe@example.com
      password: '123456'
    

    Vos lumières et volets seront automatiquement mis à votre disposition dans Home Assistant au prochain démarrage.

  • Back to the Future Digital Speedometer: Making a Replica

    For a long time now, I’ve been wanting to create a replica of Back to the Future’s digital speedometer. It’s a prop used in the movie that’s placed on the DeLorean’s dashboard, and can be seen multiple times throughout the trilogy. Of course, it’s mostly used as a visual element to mark when the DeLorean reaches 88 miles per hour and begins its time travel!

    I thought it would be cool to recreate it, and make it compatible with modern cars. I’ve seen very good-looking GPS models on the market, but I wanted to make something more genuine. GPS feels like cheating! There’s also a really awesome replica made by Damien De Meulemester that only uses components available in 1985, and works on a real DeLorean by adding a sensor to the speedometer. This is way out of my league, and obviously out of the question for modern cars with electronic speedometers, but it was a great inspiration to get started on this project.

    end result

    I settled on making my replica connect via a wire to the car’s OBD-II port, which is present on the vast majority of today’s cars.

    Resources

    You can find the firmware’s source code, reference material, CAD files, and more on Github.

    Preparing the build: research!

    We have to figure out the dimensions of the prop, the materials and components used, etc. Thankfully, the Internet is a great resource, and people have already done most of that for us.

    The enclosure used in the movie is apparently a Hammond 1591CGY ABS box. It’s 120 x 65 mm, so it’s not too big for a dashboard, and has a pretty good size for fitting some electronics in it.

    The displays used in the movie are three Stanley readout displays, which, unfortunately, don’t exist anymore. This technology has largely been replaced by seven-segment LED displays, and since they’re so similar, we’ll use these. The dimensions are tricky; it’s difficult to find the exact right size, but displays with a digit height of 20.3 mm seem to do the trick nicely. I’ll be using three Multicomp LS0803SRWK for this project.

    Note that the third digit is hidden by a piece of tape; to keep things simple but accurate and more power-efficient, we’ll use a third display, but without wiring it.

    The Stanley readout displays used to come with a black frame around them, which we can see in the movie. We’ll have to do without this. There are multiple solutions, including cutting a polystyrene frame, or using a sheet of black plastic, but the most elegant solution in 2017 to my eyes is 3D-printing a nice, sturdy plastic frame. If you’re using displays similar to mine in dimensions, you can use this model I made.

    At the end of the first movie, we can see the back of the speedometer a little bit better.

    back to the future back speedometer

    As you can see, it’s using some kind of DB25 sub-D plug, which is usually found on old computers as a parallel port (used for printers and such). Not terribly convenient, but not too hard to find!

    The Dymo labels found on the front of the box—famously reading SET TO 88—might be one of the trickiest to reproduce today, if you don’t have the right hardware. Modern Dymo machines usually print in 2D using a different font, but the labels we need are 3D (embossed) and 12 mm high. 9 mm embossed labels can be found, but 12 mm ones are rarer.

    We’re now mostly good on our “exterior” stuff; our speedometer should be pretty good-looking if we can get all of these parts.

    Build process

    I’m using an Arduino Nano (compatible) board for this project. It’s got a UART interface, enough I/O ports, and runs at 5V. It’s also super tiny and will fit nicely in the enclosure.

    We’ll need to get our Arduino to communicate with the car’s CAN bus to get the vehicle speed. Fortunately, this is all pretty easy, using the Freematics UART OBD-II adapter; it’s made for Arduino and provides a simple ELM327 interface that’s compatible with most CAN standards. It can even provide power to the board and has simple-to-use libraries, so it’s perfect for our needs.

    I had some creative choices to make when it comes to the build. I chose to include an ON/OFF slider on the back, next to the plug, to make sure the speedometer doesn’t drain the battery when the engine is off. It’s not a hard switch: it signals the Arduino to put itself and the Freematics adapter into sleep mode. I also included a speed adjustment potentiometer which you can use to calibrate the display with your actual speed.

    IMG_1453

    The Arduino’s firmware development was a tough task, as I had to learn a lot about interrupts, serial communication and display driving in the process. In the end, it’s designed as a state machine with three states (sleep, connecting, connected).

    The 7-segment displays are driven using a fork of the SevSeg library that tweaks the segments to reflect the ones used on screen (no top/bottom bar on 6 and 9, respectively) and always displaying the decimal point.

    The OBD data is polled often, and when we get the current vehicle speed, we display it by going through all the numbers in between (with a linear interpolation). That was a very important point for me, because that’s how it is on screen, and no replica seemed to do this except for De Meulemester’s.

    I started by making a basic prototype of the logic board on a breadboard and trying to make it work as well as possible with my car. I got into trouble when it came to interrupts and took a while to finish that whole system; I worked on the hardware parts in the mean time.

    Once I had a working prototype, I finally could solder the whole thing (which also took some effort) and put it into its box!

    Retrospective

    This was a great project to both attempt to build hardware and play with Arduino. The electronics involved are pretty simple but still made me ask some interesting questions that are definitely useful in any project: What’s a pull-up resistor and why is it needed? How do you wire multiple 7-segment displays, and what is multiplexing? How do you handle interrupts and switch between different tasks at the same time (boy was that a tricky one).

    I’ve made a few mistakes, of course, and there is certainly a lot to be improved by more skilled DIY-and-BTTF-enthusiasts (if you’re one of them and decide to follow my steps, please send me a tweet 👌).

    Using Molex connectors was, in retrospect, not such a good idea. I thought it would improve modularity; but whereas in computer science that doesn’t mean many drawbacks, in electronics it means wasted space. The enclosure isn’t that small, but the connectors are pretty big and I certainly could have done without them and the long-ass cables I used for them.

    end result

    I could probably also improve the constant polling of the serial line, linear speed interpolation (using the accelerometer data that comes with the adapter?), and display multiplexing.

    Overall, this was a lot of fun. I hope you liked it too! 😎