Official Ruuvi App: Weather Station


The fact that only the first 8 bytes are encoded MUST be indicated in the specs… I wasted a lot of time figuring that one out.

Second, in what way does that make formats 2 an 4 “compatible”? All you have is a byte array, format 4 has one more byte than format 2, what problem are you trying to solve?

Lastly… do you plan to change the MAC address? That looks like a pretty good ID to me.


You can decode the byte if you wish, it’s a base64 compatible character. Some decoders have issues with the missing last 3 characters, i.e. you might have to add padding in your code.

MAC address would be nice, but it does not fit in the URL. You can use MAC address as ID in RAW mode (format 3) which sends binary data in advertisement.



Thanks for answering

My problem is that I could not find a way to decode the full string even when using “=” for padding. Something did seem a bit off with the encoded string but I could not figure out what.

As for my comment on the MAC address… Either you use the URL as-is and access the site, which will ignore the extra bit of information (as far as the user goes anyway). Or you will want to process the information yourself, which means you have to retrieve the information from the advertised packet and it just happens that the packet also contains the MAC address of the sender… so I still don’t see what “use case” you had in mind when adding that ID byte. Please do enlighten me.



The extra byte was added since there was room for one more byte and a way to identify the tags was most commonly requested feature. The would benefit from some additional work, but we’ve recently been busy with something else - stay tuned for the big update :slight_smile:



I have 2 question regarding the “accelerometer” data output by the Weather station application.

As I was logging the data (with the sensor not moving), I could not help but noticing that the resulting vector was closer to 981 than to 1000. The doc indicates that the units are in milli-g so I would have expected the sensor value to return 1000 or something close when the sensor would be at rest. I looked at the sensor datasheet and there also it seems that milli-g is what the sensor outputs. I then looked into the source code and saw that in LIS2DH12.c the accelerometer data are *1000 / 1024 … Why is that? I am not sure that is correct… It would also explain the discrepancy I saw when logging the data

From what I understand, it looks like the accelerometer is programmed to use a 1 Hz update with the “Stream” method (i.e. no FIFO any new data overwrites the old data) I would thus expect that any movement would show up in the data within 1 secs at most, but it is not the case. It takes several seconds before it shows up and it also appears the same data is repeated for several seconds. Any idea what is going on?

My plan it to use RuuviTag both as a (differential) environmental logger but also as a security device that could be armed and trigger an alarm when a movement is detected. You could for example attach it to a door.The sensor seems to be able to do that natively, with its “6D” capability and it talks about “Unknow zone” but I can’t seem to find any definition of that. any pointer?



This is a bug in scaling the value, proper solution for scaling would be to scale the values with resolution/scale factor given in datasheet. Thanks for reporting.

Broadcast data is updated once per second, however the internal sensor update is not synched to reading data from sensor and broadcasting data is not synched to data reads. Therefore it’s possible to have 2-3 seconds worst case latency in seeing new data.

For more up-to date driver please see .
You might also be interested in BURST mode implemented there, it samples the accelerometer at 25 Hz and stores the results to FiFo, which is the read at 1 Hz interval. This should allow you to detect faster movements.

These will eventually be merged into master, however I cannot promise exact schedule on this yet.

Orientation alone is probably not going to be enough, as opening the door alone will not change the sensor’s orientation towards gravity. You might have to look at impulses in acceleration or varying signal strength if the receiver is by the door.



Thanks for the quick reply

Looks like the scaling is already in there… it’s just that extra step, from 1024 to 1000 that seems to be off.

My plan is that, once in place and non-moving, you run a calibration process, so you have a baseline for each axis and you can make that their 0. Now you can calculate the movement vector and decide if it does represent a movement.

Anyway, I first need to get the development environment working… I’ve downloaded the “appliance” and got it to run alright. I did the “upstream” on the git repo… and I had to choose a branch (I took “master”) But after that it fails miserably… The make fails because there are missing makefiles, and the file structure of the SDK seem to have changed, so I can’t seem to find what to do with the eec_ package. Is that appliance image still useable?




I think you might run into issues with SDK version on current master, as the bootloader is complied against 12.3 and weather station against 12.2. This can be fixed by manually downloading and unpacking missing SDK version

Problem with ECC is caused by the fact that ECC library is external to Ruuvi and Noridc SDK. The compilation instructions at readme are ok, please follow the link to Nordic infocenter on how to install ECC libraries inside SDK.



OK I got it to compile… but for some reason it seems that 3 versions of the nRF5 SDK were necessary: 12.0, 12.2 and 12.3. Is that what is supposed to happen?

It looks also that the ZIP packages were automatically created under SDK11 and SDK12… not sure which one to use?

What are the chances I could brick a Ruuvi?


12.0 Should not be needed, but if you have some older version of makefile it will be downloaded.

Makefile of each project points to proper SDK. On new projects I recommend 12.3

Low, however it is possible by generating packet for NRF52840. Please be sure to use proper generation command.
You can update the bootloader on RuuviTag to sdk12.3 bootloader, that has fixed some bricking bugs related to linker script differences between applications.



So I installed the 12.3 bootloader, thank you.

I then compile the whole ruuvi_fw with SDK12.3 I had to modifiy a few Makefile’s (eddystone lib is no longer experimental) and had to create a link for a .h file (Did affect EddyStone app, not sure for Weather app).

Now I created a zip file. It warned me about using a “debug” flag and seem to indicate that it is “bootloader” dependent. Is that OK with the 12.3 bootloader?

Lastly… any last word before I go out on a limb and install my slightly modified Weather app?



I looked into updating the ruuvi firmware into SDK 12.3, there was some breaking change in SDKs. You might want to try 12.2 - or please make a pull request if the port works.

Yes, the bootloader is in debug mode to allow people to upload anything they want to the RuuviTag. Production version would enforce version checks.

Good luck and let us know how it goes :slight_smile:



Well I did it and it worked. I only tried the “Weather Station” app bit this was OK. I made some changes to verify that I was using the software I had compiled… but yes it was OK.

I also made a change to the way the accelerometer value are “scaled” using “m-g per bit” and “bit resolution” and it does seem to wok. I find this clearer than what was there before of what “ojousima” is doing, but it hasn’t been fully tested ;). I do it like this

      add 32768,  since the accelerometer is a 16 bits 2's complement the full range is
                          from -32768 to +32767 so this moves the value range into positive territory

      clean LSB    essentially >> (16 - resolution) with resolution 8, 10 or 12

      substract (1<<(resolution-1) )  so we get back the signed info within the set resolution

     scale         based on the number of m-g per bit

I also added a “distro” target to the Makefile. Currently it only creates the weather app zip file. I also can automatically upload it to google drive with the use of gdrive but I comented that out for now).

So givent that, if you still want it, I’ll be glad to create a pull request.

I also have a problem. I have 2 Ruuvi tags, and one of them got stuck into “booter” mode. I can access it, upload zip and what not, but it is stuck in booter mode and the app won’t start… even after pressing button, removing the battery,… etc. I don’t think it is a problem with the uploaded app, since the other Ruuvi was running the same app and I tried uploading the standard app. So I am afraid that the button is stuck. Any advice?

After a few tries, uploading my app, the thing resets itself properly… no idea why.




Well I was looking at your updated code… and I think there is a bit of a problem with the BURST mode (I haven’t tested anythng yet ;)) In the burst mode, you set High Resolution bit, i.e. 12 bits and use the FIFO. The problem is that the manual states (3.6)

Not 12 bits…



Thanks for the report, looks like 10-bit mode would be better in this use



Me again… I hope I am not bothering you, well not too much anyway.

I’ve looked more into your updated LIS2DH12 module. I’ve actually (locally) made a number of modifications to it as well as the “main.c” in the weather app to reflect the changes… Now I am stuck coz’ I need to debug this thing and that requires hardware I don’t have.

Anyway… there is a number of issues I want to raise about that updated driver.

   1- I do not think FIFO mode is properly set
        The app does set the LIS2DH_FIFO_EN_MASK on Reg5 but
        it does not set FIFO_CTRL_REG, which I think means it is still
        in bypass mode

   2- I really thing that when using the FIFO, you should use the stream mode.
       it should really simplify your life... essentially it will take care of itself
       You can also avoid the reset in timer_lis2dh12_event_handler (which I thing you were 
       doing wrong anyway the reset should occur with FIFO_CTRL_REG not Reg5)

   3- g_sensorData should have a size of 32, which is the maximum possible number of data you 
       can read from the FIFO, and you should use FIFO_SRC_REG to figure out how many
       data can be read. Currently it is way too ad-hoc.

   4- Combining 2 and 3 above, you should be able to handle every case without much trouble.

   5- LIS2DH12_getALLmG should return LIS2DH12_RET_NULL when all data have been
       read from the "cache"

   6- When reading the data, the weather app should get to the latest one, something like 
      (depends on 5)
              while (LIS2DH12_RET_OK == LIS2DH12_getALLmG(&accx, &accy, &accz)) {
                    acc[0] = accx;
                    acc[1] = accy;
                    acc[2] = accz;

Just my 2 cents… Now, what do I need to debug this thing?




Thanks for the feedback, there’s a reason on why the driver is not yet merged :wink: We’d be happy to help with debugging, I’ll PM you the details. Please join our slack channel if you haven’t already (send email to, It’s generally quicker to get answers in there.

I haven’t yet had time to look at the pull request / driver changes in detail, I’ll do that in next few days



I am starting to get my head around how the thing works.

I have now a version of the Weather Station application that will update the accelerometer data in “real time” . It can be retrieved at Experimental Weather Station app (It works for me, but use at your own risks)

In this version, the environmental variables (temperature, humidity, pressure) are updated every 5 secs like in the original, but the accelerometer data will be updated faster. Like in the original, the beacon advertises data at 2Hz.

Pressing the “mode change” button will loop through the following modes:

  1. Eddystone URL
    This is the same mode as before. Only temperature, humidity and pressure are
    available through the broadcast URL

  2. High Resolution
    This is similar to the previous highres mode. The accelerometer values are sampled
    and updated at 1 Hz. Use 10 bits, normal power mode (2 µA) at 1 Hz

  3. High resolution mode 2
    This is similar to the High Resolution mode. The accelerometer data are sampled
    at 10 Hz and updated at 2 Hz. Use 10 bits, normal power mode at 10 Hz (4 µA).

  4. High Resolution mode 3
    The accelerometer data are sampled at 25 Hz and updated at 2 Hz. Use 8 bits, low power mode at 25 Hz (4 µA).

In both mode 2 and 3, the sample selected to update the beacon value is the one presenting the largest variation to the theoretical rest value i.e.

  abs(1000 - sqrt(x**2 + y**2 + z**2))

Note that in mode 3, because it is using 8 bits (i.e. 16 millig values) you never get 1000, only 992 or 1008.

If you use it, let me know what you think.


Help needed- Sending notification/advertising to RaspberryPi-
IDEA: Mail alarm?

Nice work!

I power profiled the application, on average:

  • 33 µA on modes 1 & 2
  • 40 µA on mode 3
  • 45 µA on mode 4
    I’d expect battery life to be 2-3 years in indoor environment.

You’d might be interested in Nordic tutorial about radio event notification: that should allow you to raise interrupt right before advertisement is sent and update the data, allowing faster data rates and smaller delay between sample and broadcast.



I am new to this, but that seems quite good.

Interrupts is a good idea, and we could get rid of the intermediate buffer as long as the sampling and broadcast rates are compatible.

I was thinking more along the line… Broadcast the environmental data more slowly (say 30/60 secs) using the Eddystone URL (reusing the IMO useless id byte to provide extra precision for temperature whilst remaining compatible with the current scheme) and use an “Immediate Alert Service” profile to signal movement… but I still have a lot of question marks…( is IAS possible over a LE conect?)