{"id":20678760,"url":"https://github.com/helins/clojure-of-things","last_synced_at":"2025-07-16T18:05:02.723Z","repository":{"id":117734554,"uuid":"124905497","full_name":"helins/clojure-of-things","owner":"helins","description":"Documentation about how to run Clojure on the Raspberry Pi","archived":false,"fork":false,"pushed_at":"2019-03-14T09:37:14.000Z","size":13,"stargazers_count":64,"open_issues_count":0,"forks_count":2,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-06-04T23:11:59.195Z","etag":null,"topics":["clojure","documenation","raspberrypi"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/helins.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-03-12T14:54:33.000Z","updated_at":"2024-12-03T21:19:49.000Z","dependencies_parsed_at":null,"dependency_job_id":"9e51585e-4330-412b-a826-ccee0fc655a3","html_url":"https://github.com/helins/clojure-of-things","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/helins/clojure-of-things","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helins%2Fclojure-of-things","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helins%2Fclojure-of-things/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helins%2Fclojure-of-things/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helins%2Fclojure-of-things/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/helins","download_url":"https://codeload.github.com/helins/clojure-of-things/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/helins%2Fclojure-of-things/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265528855,"owners_count":23782769,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","documenation","raspberrypi"],"created_at":"2024-11-16T21:22:05.764Z","updated_at":"2025-07-16T18:05:02.715Z","avatar_url":"https://github.com/helins.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Running Clojure on the Raspberry Pi\n\n[![Create Commons\nLicense](https://i.creativecommons.org/l/by-sa/4.0/88x31.png)](http://creativecommons.org/licenses/by-sa/4.0/)\n\nThis work is licensed under a [Creative Commons Attribution-ShareAlike 4.0\nInternational License](http://creativecommons.org/licenses/by-sa/4.0/).\n\n## 1. Rationale\n\nDynamic languages have gradually become prominent for building more or less\nsmart devices. The Raspberry Pi is a perfect example of cheap but powerful\nhardware used for building such of devices. While Python and NodeJS are popular\ndynamic languages, this documentation explains the advantages of using Clojure\nand provides various how-to's. It aims to be accessible to people familiar with\nClojure and the Raspberry Pi ecosystem while remaining beginner friendly.\n\n### 1.1. Asynchronous programming\n\nThe smarter the device and the more asynchronous its behavior will be. Clojure\nprovides strong concurrency primitives as well as the excellent\n[core.async](https://clojure.org/reference/compilation) library, an\nimplementation of [communicating sequential\nprocesses](https://en.wikipedia.org/wiki/Communicating_sequential_processes)\nakin to the go programming language.\n\nFrameworks such as the [Robot Operating\nSystem](https://en.wikipedia.org/wiki/Robot_Operating_System) describe the\nimportance of loosely coupled modules talking via\n[pub/sub](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern).\nUsing Clojure, arbitrarly complex programs can be written by composing modules\nexchanging data asynchronously.\n\n### 1.2. Unified development\n\nClojure targets Java as well as Javascript and code can be shared between\nplatforms. This result in a unique experience of trully [writting once and\nrunning anywhere](https://en.wikipedia.org/wiki/Write_once,_run_anywhere). Other\nlanguages providing such multi-plaform support are not as mature yet.\n\nThe process of sharing code between devices, back-end and front-end greatly\nsimplifies data modeling. Utilities written for describing and validating data\ndo not need to be written again in another language resulting in perfect\nconsistency. This alone eliminates an important class of bugs besides being a\nvaluable time saver.\n\nClojure now ships [Spec](https://clojure.org/about/spec), a core library for\ndescribing, validading and generating data amongst other things. It provides a\nstandard framework for data modeling. Typically, the robustness of field devices\nand the system they belong to is assessed by feeding test data for [fuzzy\ntesting](https://en.wikipedia.org/wiki/Fuzzing). This is a laborious, error\nprone and unsatisfying process. Using Spec, data can be generated automatically,\nwhich means that not much is then needed for testing the field devices, or\nanything in the system, by feeding valid and unvalid data. Much bugs usually\ndiscovered in production can be uncover using this method.\n\n## 2. Choosing and installing a JVM\n\nAs of today, the three main fully-fledged Java 8 environments supported by the\nRaspberry Pi are :\n\n- Oracle\n- OpenJDK\n- Zulu Embedded\n\nAs far as we know, OpenJDK is still not optimized and runs a lot slower than\nOracle, making it unsuitable. The latter is optimized but requires a license\nwhen used for anything else than education and personal projects. Hence, our\nrecommended choice is [Zulu\nEmbedded](https://www.azul.com/solutions/embedded-and-the-iot/) by [Azul\nSystems](https://www.azul.com/). It is fully certified and offers performance\nparity with Oracle. More importantly, it is open source and freely downloadable.\nFollowing the open source model, the company finances the project by providing\npaid support.\n\nZulu Embedded releases are available\n[here](https://www.azul.com/downloads/zulu-embedded/) for manual installation.\n\nThe easiest way is to [add the Azul Systems debian repository and use\napt](http://zulu.org/zuludocs-folder/#ZuluUserGuide/PrepareZuluPlatform/AttachAPTRepositoryUbuntuOrDebianSys.htm)\n:\n```\n$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0x219BD9C9\n$ echo 'deb http://repos.azulsystems.com/debian stable main' | sudo tee /etc/apt/sources.list.d/zulu.list \u003e /dev/null\n$ sudo apt update\n$ sudo apt install zulu-embedded-8\n$ java -version\n```\n\nJava 9 is net yet supported by Azul Systems but it is probably a matter of time.\n\n## 3. Configuring IO\n\nThere are no special requirements for using GPIO, I2C or SPI. Nonetheless,\nregardless of Clojure, the serial port behaves oddly on the Raspberry Pi 3. Many\narticles and posts have been written on the subject. In short, the Raspberry Pi\n3 is equipped with two built-in\n[UART](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter)'s\nfor serial communication :\n\n- __/dev/ttyAMA0__ is a high performance hardware UART used by bluetooth.\n- __/dev/S0__ is a mini UART, much less capable, used by the serial port.\n\nRunning the serial port on the mini UART will be unsuitable for many\napplications. The solution is to choose an alternative [device\ntree](https://en.wikipedia.org/wiki/Device_tree) overlay in\n__/boot/config.txt__.\n\nThis line will swap bluetooth and the serial port, meaning bluetooth will run on\nmini UART, which might be enough or not at all :\n```\ndtoverlay=pi3-miniuart-bt\n```\n\nThis line will simply switch bluetooth off and is recommended if bluetooth is\nnot needed :\n```\ndtoverlay=pi3-disable-bt\n```\n\nAfter a reboot, the serial port will be accessible at __/dev/ttyAMA0__ just like\non prior Raspberry Pi models. Read more about this matter\n[here](https://www.raspberrypi.org/documentation/configuration/uart.md).\n\n## 4. Leiningen\n\n[Leiningen](https://leiningen.org/) is installed as usual. Starting a REPL is\nusually slow, much slower than on a desktop and the process might timeout. This\nis preventable by adding this option to the project file :\n\n```clj\n{:repl-options {:timeout 180000}}  ;; 3 minutes for example\n```\n\nOnce the REPL is launched and everything is compiled, it behaves as usual. For\nproduction, projects can be compiled on a development machine rather than on the\nRaspberry Pi itself.\n\n## 5. Development via SSH\n\nWhile it is possible to write code on the Raspberry Pi, it is probably no\nreplacement to your desktop environment. The easiest way is to keep everything\non your machine and use\n[SSHFS](https://www.digitalocean.com/community/tutorials/how-to-use-sshfs-to-mount-remote-file-systems-over-ssh)\nto mount the folder where the project resides on the Raspberry Pi. This allow\nfor launching a REPL on the device without having to keep files locally.\nOtherwise, it is possible to use [rsync](https://rsync.samba.org) and\nsynchronize files everytime before starting the REPL, but it is somewhat less\nefficient.\n\nThe REPL can be made available to the local network by typing the following\n(where $PORT is your favorite port) :\n\n```\n$ lein repl :start :host 0.0.0.0 :port $PORT\n```\n\nThe rest is just traditional Clojure development of connecting your text\neditor/IDE to the REPL and doing wonders.\n\n## 6. Optimizing uberjars\n\nFor better performance and faster boot time, it is best for the user to be\nacquainted with the [compilation](https://clojure.org/reference/compilation)\nprocess and its various options. This is true for any environment but become\nmore relevant for the Raspberry Pi as it is much more limited than a desktop\ncomputer or a server.\n\n## 7. Recommended libraries\n\n### 7.1. Miscellaneous\n\n#### 7.1.1. Logging\n\nThere are a few logging libraries for Clojure but the most widely used and\nrecommended one is [Timbre](https://github.com/ptaoussanis/timbre). It is fairly\neasy to write log appenders and be up and running in minutes.\n\n#### 7.1.2. Modules\n\nComplex programs are often modular and it is easier to extend modular programs.\nWe recommend [Integrant](https://github.com/weavejester/integrant), a great\nmicro-framework for writing modules, connecting them and managing them.\n\n### 7.2. IO\n\n#### 7.2.1. GPIO\n\nThe Raspberry Pi community often relies on either\n[wiringPi](http://wiringpi.com) or [PIGPIO](https://github.com/joan2937/pigpio),\ntwo common C libraries for handling GPIO lines among other things. Higher level\nlanguages often provide wrappers, specially for wiringPi. The main library for\naccessing wiringPi from Java is [PI4J](http://pi4j.com), although it is not\nactively maintained anymore. Any attempts (including our own) to provide\nbindings to PIGPIO resulted in an utter failure. For unknown reasons, sooner or\nlater the JVM presents unexpected segfaults or early terminations, both when\nusing [JNA](https://en.wikipedia.org/wiki/Java_Native_Access) and\n[JNI](https://en.wikipedia.org/wiki/Java_Native_Interface).\n\nIn any case, those C underlying libraries directly write to /dev/mem or\n/dev/gpiomem. While this is fast, a number of problems arise. For instance,\nthere is no automatic clean-up which means that if an application crashes for\nany reason, the state of the lines remains as is.\n\nA best approach would be to rely on a proper Linux driver. For years, driving\nlines has been done via the SysFS approach by exporting lines as files and then\nperforming simple IO. Unfortunately, this was slow and presented the same kind\nof problems as writing directly to /dev/mem. The whole process was messy.\n\nLinux now offers a new API since version 4.8. Each GPIO chip is accessible as a\nchar device. This new scheme is surprisingly fast, offers better support for\ninterrupts as well as a number of other desirable features. For instance, lines\nneed to be properly requested. A single handle can drive several lines at once\nand when it is released, whether on purpose or when the process terminates,\nlines go back to their initial state.\n\nThe only java library built for this new API is\n[dvlopt/linux-gpio.java](https://github.com/dvlopt/linux-gpio.java). It serves\nas the basis for\n[dvlopt/linux.gpio.clj](https://github.com/dvlopt/linux.gpio.clj), a\nhigher-level clojure wrapper. Furthermore, relying on a Linux utility means\nthose libraries can run on any machine as they are not specific to the Raspberry\nPi.\n\n#### 7.2.2. I2C\n\n[dvlopt/linux.i2c.clj](https://github.com/dvlopt/linux.i2c.clj) is the only\nClojure library for talking to I2C slave devices. Here are current sub-libraries\ntargeting specific sensors and devices :\n\n- [bme280](https://github.com/dvlopt/linux.i2c.bme280), a popular environment\n  sensor built by Bosh.\n- [horter-i2hae](https://github.com/dvlopt/linux.i2c.horter-i2hae), a simple A/D\n  converter.\n- [mcp342x](https://github.com/dvlopt/linux.i2c.mcp342x), a family of A/D\n  converters.\n\n#### 7.2.3. Meter-Bus\n\n[JMbus](https://www.openmuc.org/m-bus/) is the only stable and actively\nmaintained Java library for talking to Meter-Bus slaves, typically meters. It\nrequires Meter-bus converters such as those provided by\n[Solvimus](http://www.solvimus.de/en/).\n\n[dvlopt/mbus](https://github.com/dvlopt/mbus) is a Clojure wrapper around JMbus.\nAs of today, it supports Meter-Bus via the serial port and TCP/IP.\n\n#### 7.2.4. Serial port\n\nTalking via the serial port from the JVM has always been a bit burdensome.\n[Purejavacomm](https://github.com/nyholku/purejavacomm) aims to provide a\nmulti-platform compatibility without any prior installation of native libraries.\nTo our knowledge, [Clj-serial](https://github.com/peterschwarz/clj-serial) is\nthe only Clojure wrapper for Purejavacomm.\n\nHistorically, RXTX has been widely used for serial IO. The project is now\ndiscontinued. However, [openmuc/jrxtx](https://github.com/openmuc/jrxtx) aims to\nprovide a replacement as well as a few improvements. The slight downside is that\nit requires the installation of native libraries. Because a lot of legacy\nprojects (and a few present ones) relies on RXTX, this library might be\npreferable over purejavacomm. [dvlopt/rxtx](https://github.com/dvlopt/rxtx) is a\nsimple to use clojure wrapper.\n\n#### 7.2.5. SPI\n\nBasic SPI utilities are proposed by the aforementioned PI4J library. To our\nknowledge, there is not any specific Java library.\n[dvlopt/spi](https://github.com/dvlopt/spi) is an attempt to provide bindings to\nthe Linux API but remains a poorly documented experiment for the time being.\n\n### 7.3. Networking\n\n#### 7.3.1. HTTP and websockets\n\nRaspberry Pies are often used for running small HTTP servers.\n\nWhile there are quite few libraries for HTTP servers and clients, we recommend\n[Aleph](https://github.com/ztellman/aleph). It is a popular choice and provides\nasynchronous utilities for spinning up a server or performing requests as well\nas for executing requests. It offers great support for\n[websockets](https://en.wikipedia.org/wiki/WebSocket).\n\n#### 7.3.2. MQTT\n\n[MQTT](https://en.wikipedia.org/wiki/MQTT) has become popular for internet of\nthings projects for providing bidirectional communication organized around\ntopics. It provides useful functionalities over something like barebone\n[websockets](https://en.wikipedia.org/wiki/WebSocket).\n\nThe [Paho MQTT Java client](https://github.com/eclipse/paho.mqtt.java) is\nprobably the most active and well-maintained MQTT client library in the\necosystem.\n\n[dvlopt/mqtt](https://github.com/dvlopt/mqtt) is a Clojure wrapper around the\nPaho library.\n\n## 8. Recommended tools and practises\n\n### 8.1. Writing modular programs\n\nComplex programs benefit from being modular in order to remain extensible.\nNetworking and handling various IO's will result in plenty of asynchronicity.\nCore.async can provide a pub/sub event bus and modules can subscribes to the\nneeded topics and start the necessary goroutines. The event bus would in itself\nbe a top-level module requested by all other participating modules.\n\nHowever, when an integrant system is started, modules are initialized\nsynchronous after resolving dependencies between them. If a module starts\npushing values asynchronously on the event bus before other dependent modules\nare ready, the outcome will be data loss and inconsistency. Given this fact,\nmodules producing values should wait a signal. In practise, besides the event\nbus should be a promise channel serving the purpose of signaling that the system\nis ready to work. This channel should deliver the signal once integrant returns,\nmeaning that every module is ready and had the change to subscribe to the needed\ntopics.\n\n### 8.2. Network over 3G/4G\n\nThe [Huawei e3772](https://consumer.huawei.com/en/mobile-broadband/e3372/) USB\n4G dongle is recommended as it is supported by Raspbian and does not require any\ninstallation nor configuration. The only shortcoming is that it auto-disconnect\nafter a few minutes. There is no way to disable this behaviour but it can be\nconfigured to raise the interval to two hours. A simple solution for keeping the\ndongle active is to setup a CRON job for pinging google or anything else within\nthe disconnect interval.\n\nThe dongle runs a webserver accessible like a typical router. Run this in the\nterminal and find out which address it is :\n\n```\n$ ip route\n```\n\n### 8.3. Remote management\n\n[Ansible](https://www.ansible.com/) is an administration tool used for managing\nservers using declarative configuration files. It leverages SSH and hosts do not\nrequire any setup. A machine can actually manage itself and this can be used as\na remote update mechanism. A Raspberry Pi can indeed be prepared for\nperiodically fetching configuration files via FTP or by any other mean and then\nuse Ansible on itself. An alternative similar solution would be to take\nadvantage of\n[ansible-pull](http://docs.ansible.com/ansible/latest/ansible-pull.html).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhelins%2Fclojure-of-things","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhelins%2Fclojure-of-things","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhelins%2Fclojure-of-things/lists"}