After you have successfully installed CouchDB as decribed here, you can simply start it like this:
~$ couchdb start
This short example is build upon the offical tutorial of the core API. Lets create a new database called temperatures.
~$ curl -X PUT http://127.0.0.1:5984/temperatures
Inserting new documents into the temperatures database is as simple as creating a database:
~$ curl -X PUT http://127.0.0.1:5984/temperatures/e7e56c6c-822f-442d-a707-973e20fc8d87 -d '{"celsius": "23.73", "timestamp": 1461326744.1631064}'
I used the Python3 uuid module to create the UUID e7e56c6c-822f-442d-a707-973e20fc8d87 which is used as the document ID. I also created a view called "by-timestamp" inside the design document with the help of Futon and wrote the following map function:
function(doc) {
var celsius, timestamp;
if (doc.celsius && doc.timestamp) {
celsius = doc.celsius;
timestamp = doc.timestamp;
emit(timestamp, {temperature: celsius});
}
}
Since the view can be parameterized with sort and filter options, its possible to make a GET request that yields the newest document:
http://127.0.0.1:5984/temperatures/_design/foo/_view/by-timestamp?descending=true&limit=1
Furthermore, I created a show called "celsius" in the design document, which adds some HTML around the document content. To insert a show into the design document, the key "shows" must be added with the following value:
{
"celsius" : "function (doc, req) {
return '<p>Temperature: ' + doc.celsius + '°C</p>';
}"
}
The following URL can be used to query the celsius show with a document ID:
http://127.0.0.1:5984/temperaturues/_design/foo/_show/celsius/1644712d-e5ab-48c3-aaa7-ac6eb75b750b
That's it! Any easy way to persist your data, but the concepts behind views and shows are a bit tricky.
Sunday, April 24, 2016
Thursday, April 7, 2016
Handling null in Scala
When you are using Java APIs, you might find yourself in the situation that you have to deal with null. In plain Scala, usually you wouldn't use null, but use an Option instead.
The apply method of the Option singleton object has a nice way to convert null to None (see Option.scala):
Hence, you can do Option(null) and you'll get None.
A simple example that handles null in a safe way:
val maybeNull = someJavaMethodThatMightReturnNull(42)
Option(maybeNull).foreach(println)
On the other hand, if you do Some(null) you'll get back Some(null).
The apply method of the Option singleton object has a nice way to convert null to None (see Option.scala):
def apply[A](x: A): Option[A] = if (x == null) None else Some(x)
Hence, you can do Option(null) and you'll get None.
A simple example that handles null in a safe way:
val maybeNull = someJavaMethodThatMightReturnNull(42)
Option(maybeNull).foreach(println)
On the other hand, if you do Some(null) you'll get back Some(null).
Wednesday, March 30, 2016
Measuring water temperature in food-safe applications with Raspberry PI + PT100 sensor + Tinkerforge PTC Bricklet
I was looking for a temperature sensor (thermometer) that can be used with a Raspberry PI for measuring water temperature in food-safe (lebensmittelecht) applications.
The sensor should satisfy the following requirements:
The problem is, that a PT100 sensor cannot just be connected with a Raspberry PI, because you need an analog-digital converter. Lucky as I am, the company Tinkerforge offers some very nice modules to improve this situation. To connect a PT100 temperature sensor, you can use the Tinkerforge PTC Bricklet which gives you the current temperatur in Celsius as an integer number. Its getting even better: Tinkerforge offers an easy to use API for the "most popular" programming languages - including Python.
To connect the Tinkerforge PTC Bricklet with the Raspberry PI, you also need the Tinkerforge Master Brick, which is capable of connecting up to four Bricklets and has a mini USB connector to connect it with a computer.
The first thing to do, is to install brickd. When brickd is up and running, I recommend to change the following two lines in /etc/brickd.conf:
ipcon.authenticate('topsecret')
Replace 'topsecret' with your authentication password. Before you can make use of the Tinkerforge API, you have to install the bindings for the language that you want to use. In our case, the easiest way to do that, is to download the ZIP file with the Python bindings and copy the directory source/tinkerforge to your prefered location on your harddisc. To be able to import the bindings from a Python script, just copy the Python script to the same location where you copied the tinkerforge directory. After this is all done, you can run the script and it will output all connected devices and their corresponding identifiers.
The sensor should satisfy the following requirements:
- food-safe
- waterproof
- heat resistant until at least 100°C
The problem is, that a PT100 sensor cannot just be connected with a Raspberry PI, because you need an analog-digital converter. Lucky as I am, the company Tinkerforge offers some very nice modules to improve this situation. To connect a PT100 temperature sensor, you can use the Tinkerforge PTC Bricklet which gives you the current temperatur in Celsius as an integer number. Its getting even better: Tinkerforge offers an easy to use API for the "most popular" programming languages - including Python.
To connect the Tinkerforge PTC Bricklet with the Raspberry PI, you also need the Tinkerforge Master Brick, which is capable of connecting up to four Bricklets and has a mini USB connector to connect it with a computer.
The first thing to do, is to install brickd. When brickd is up and running, I recommend to change the following two lines in /etc/brickd.conf:
- listen.address = 127.0.0.1
- authentication.secret = topsecret
ipcon.authenticate('topsecret')
Replace 'topsecret' with your authentication password. Before you can make use of the Tinkerforge API, you have to install the bindings for the language that you want to use. In our case, the easiest way to do that, is to download the ZIP file with the Python bindings and copy the directory source/tinkerforge to your prefered location on your harddisc. To be able to import the bindings from a Python script, just copy the Python script to the same location where you copied the tinkerforge directory. After this is all done, you can run the script and it will output all connected devices and their corresponding identifiers.
Labels:
food-safe,
lebensmittelecht,
Master Brick,
PT100,
PTC Bricklet,
Python,
Raspberry PI,
temperature sensor,
thermometer,
Tinkerforge
Monday, September 14, 2015
Debian 8.2 "Jessie" - cryptsetup: lvm is not available
After rebooting my laptop, Debian 8.2 didn't want to boot but tells me:
cryptsetup: lvm is not available
The Hitchhiker's Guide to the Galaxy says: "Don't Panic". After about 3-5 minutes, the build-in shell is loaded (initramfs). You can directly leave the shell by typing exit and the system will boot normally. I don't know the problem yet, but it also says:
modprobe: module ehci-orion not found in modules.deb
cryptsetup: lvm is not available
The Hitchhiker's Guide to the Galaxy says: "Don't Panic". After about 3-5 minutes, the build-in shell is loaded (initramfs). You can directly leave the shell by typing exit and the system will boot normally. I don't know the problem yet, but it also says:
modprobe: module ehci-orion not found in modules.deb
Saturday, August 8, 2015
Installing Oracle JDK on Debian Jessie
Hi there. I just found out yet another way to install the Oracle JDK on your Debian. There's a nice article in the Debian Wiki and you only have to follow the five steps that are listed under the "Process" section. After you have installed the new .deb package, you can simply change from OpenJDK to Oracle JDK by using the update-java-alternatives command. In my case, its the following:
# update-java-alternatives --set jdk-8-oracle-x64
# update-java-alternatives --set jdk-8-oracle-x64
Thursday, April 16, 2015
Scala Future Callback for Apache HTTP Async Client
In a recent project, I needed an asynchronous HTTP client and due to some other requirements, I decided to use the Apache Async HTTP Client. The problem is, that the Async HTTP Client uses Java's Future implementation:
After I discussed the problem with a collegue, he came up with a pretty cool solution that prepares the ground for Scala Futures. The trick is to implement the FutureCallback interface by using a Scala Promise:
class ScalaFutureCallbackImpl[T] extends FutureCallback[T] {
private val promise: Promise[T] = Promise()
def cancelled(): Unit =
promise.failure(new RuntimeException("cancelled!"))
def completed(result: T): Unit = promise.success(result)
def failed(ex: Exception): Unit = promise.failure(ex)
def getScalaFuture: Future[T] = promise.future
}
Its interesting to see, how perfect the methods from the interface can be mapped to the corresponding Promise methods. The additional method getScalaFuture is necessary to give the caller access to the underlying Scala Future. With the new implementation, we are now able to use the Apache Async HTTP Client in a more convenient way:
val httpclient = HttpAsyncClients.createDefault()
val callback = new ScalaFutureCallbackImpl[HttpResponse]
httpClient.execute(host, request, context, callback)
for {
httpResponse <- callback.getScalaFuture
}
yield httpResponse
"The result can only be retrieved using method get when the computation has completed, blocking if necessary until it is ready." [Java Futures]An example code snippet demonstrates how to send an asynchronous HTTP request. To make a long story short: accessing the result of the Future means we block the current thread. An alternative solution is to use the Apache FutureCallback interface, which also lacks the ability to access the result of the future in a non-blocking way (see example). Hence: the provided functionality does not scale well in highly concurrent environments.
After I discussed the problem with a collegue, he came up with a pretty cool solution that prepares the ground for Scala Futures. The trick is to implement the FutureCallback interface by using a Scala Promise:
class ScalaFutureCallbackImpl[T] extends FutureCallback[T] {
private val promise: Promise[T] = Promise()
def cancelled(): Unit =
promise.failure(new RuntimeException("cancelled!"))
def completed(result: T): Unit = promise.success(result)
def failed(ex: Exception): Unit = promise.failure(ex)
def getScalaFuture: Future[T] = promise.future
}
Its interesting to see, how perfect the methods from the interface can be mapped to the corresponding Promise methods. The additional method getScalaFuture is necessary to give the caller access to the underlying Scala Future. With the new implementation, we are now able to use the Apache Async HTTP Client in a more convenient way:
val httpclient = HttpAsyncClients.createDefault()
val callback = new ScalaFutureCallbackImpl[HttpResponse]
httpClient.execute(host, request, context, callback)
for {
httpResponse <- callback.getScalaFuture
}
yield httpResponse
Thursday, January 8, 2015
Thinkpad T410 Wireless (Intel Centrino Advanced-N 6200 AGN) and Debian Wheezy
It might happen that your T410 wireless doesn't work after installing Debian, because you didn't have the non-free firmware at hand.
You'll find the missing firmware at the packages site. After you downloaded and decompressed the tarball put the file iwlwifi-6000-4.ucode-9.221.4.1 into /lib/firmware and create a symlink:
# ln -s iwlwifi-6000-4.ucode-9.221.4.1 iwlwifi-6000-4.ucode
Now, its time to reboot!
You'll find the missing firmware at the packages site. After you downloaded and decompressed the tarball put the file iwlwifi-6000-4.ucode-9.221.4.1 into /lib/firmware and create a symlink:
# ln -s iwlwifi-6000-4.ucode-9.221.4.1 iwlwifi-6000-4.ucode
Now, its time to reboot!
Subscribe to:
Posts (Atom)