<img height="1" width="1" src="https://www.facebook.com/tr?id=1357777224302944&amp;ev=PageView &amp;noscript=1">

Build a Multi-Location Temperature-Monitoring System using Connext DDS & RTI Prototyper with Lua

February 20, 2014 by
|

Some employes in the northwest corner were feeling colder than the engineers on the south side of the building. The engineers, of course, thought it was simply because they were hotter than anybody else, but they took up the challenge to discover whether there was really a problem. In fact, we attempted to use our own RTI Connext DDS and a bunch of other technologies to prove how easy it is to integrate different systems together.

Our web marketing manager purchased 2 BeagleBone boards. We put one of them in his cube and the other in mine. Each board has a 1 wire temperature sensor. The sensor uses the 1-wire file system and creates an easily readable file on your system.

We decided to publish the temperature data over DDS and make it available to anyone with a smartphone. For proof of concept, we wanted to do it using as many different technologies as possible.

As shown above, the temperature sensor fed into a C application that published the data over DDS. A Raspberry Pi board collected the data. Then, using RTI Prototyper with Lua, we uploaded the data to a 3rd-party cloud database. Finally, an iOS app written in objective-C pulled the data from the database and displayed it on a mobile phone.

Embedded Temperature Publisher

With RTI Code Generator 2.0, this task was extremely easy! Here's what we did:

Created a simple IDL:

struct TempMonitor {
    string<255> id; //@key
    string<255> location;
    double temperature;
};

Ran rtiddsgen:

rtiddsgen -language C -example armv6leLinux3gcc4.7.2 TempMonitor.idl

Modified the generated TempMonitor_publisher.c in 2 places:

1) At the beginning of publisher_main() we opened the temperature file:

FILE *fr = NULL;
char fileName[1024];
float temp;
char line[80];
sprintf(fileName, "/mnt/1wire/uncached/%s/temperature", sensor_id);
fr = fopen("/mnt/1wire/uncached/%s/temperature/", "rt");

2) In the main loop, we read the file and published the data:

/* Main loop */
for (count=0; (sample_count == 0) || (count < sample_count); ++count) {
    printf("Writing TempMonitor, count %d\n", count);

    /* Modify the data to be written here */
    if (fgets(line,80,fr) != NULL) {
        sscanf(line,"%f",&temp);
        printf("Temp is %f\n",temp);
    }
    instance->temperature = (double)temp;
    sprintf(instance->id, "%s", sensor_id);
    sprintf(instance->location, "%s", description);

    /* Write data */
    retcode = TempMonitorDataWriter_write(
    TempMonitor_writer, instance, &instance_handle);
    if (retcode != DDS_RETCODE_OK) {
        printf("write error %d\n", retcode);
    }

    NDDS_Utility_sleep(&send_period);
}

The sensor_id was passed in from the command line so the application could be used on any of the BeagleBone boards without recompiling.

Compiled and ran the application with the generated makefile:

gmake -f makefile_TempMonitor_armv6leLinux3gcc4.7.2

Added a single line to /etc/rc.local it ran every time the BeagleBone started:

/root/TempMonitor_publisher 36 0 60 28.AE01EF020000 "gp-cube" &
                            |  |  |  |               |
domainId -------------------|  |  |  |               |
numberOfSamples (0=infinite) --|  |  |               |
publish every 60 seconds ---------|  |               |
temperature sensor id ---------------|               |
location --------------------------------------------|

Restarted rc.local to start data flowing on the network:

We could then run rtiddsspy on any other machine on the network and subscribe to it.

./lib/x64Darwin10gcc4.2.1/rtiddsspy -domain 36 -printSample

RTI Data Distribution Service Spy built with NDDS version 1.6a.00--C1.6a.00--C++1.6a.00
Copyright 2012 Real-Time Innovations, Inc.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
NddsSpy is listening for data, press CTRL+C to stop it.

source_timestamp   Info  Src HostId  topic               type
-----------------  ----  ----------  ------------------  ------------------ 
1370626818.324170  W +N  0A0A64A4    TempMonitorTopic    TempMonitor
1370628079.478908  D +N  0A0A64A4    TempMonitorTopic    TempMonitor

id: "28.AE01EF020000"
location: "gp-cube"
temperature: 71.487503

Copied the executable to the other BeagleBone boards and set up rc.local to have 3 weather stations running in the office.

RTI Connext DDS allows you to take systems and integrate them seamlessly with little effort. If you already store data in cloud-based storage with a RESTful API, we can gather all the data published over DDS by the different weather stations and store it in the cloud. Using RTI Connext Prototyper and the scripting language Lua, it only takes a few minutes to integrate a 3rd-party service. Here's how we did it…

Copied Prototyper to a Raspberry Pi board and created an XML file that specified the type:

<types>
  <struct name="TempMonitor">
    <member name="id" key="true" type="string" stringMaxLength="255"/>
    <member name="location" type="string" stringMaxLength="255"/>
    <member name="temperature" type="double"/>
  </struct>
</types>

Registered the type:

<domain_library name="MyDomainLibrary">
  <domain name="TempDomain" domain_id="36">
    <register_type name="TempMonitor" kind="dynamicData" type_ref="TempMonitor" />
    <topic name="TempMonitorTopic" register_type_ref="TempMonitor"/>
  </domain>
</domain_library>

Created a participant with one subscriber:

<domain_participant name="TempMonitorSub" domain_ref="MyDomainLibrary::TempDomain">
  <participant_qos base_name="QosLibrary::DefaultProfile"/>
  <subscriber name="MySubscriber">
    <data_reader name="TempReader" topic_ref="TempMonitorTopic" />
  </subscriber>
</domain_participant>

Prepared to receive and print the data with a simple Lua script:

for name,reader in pairs(CONTAINER.READER) do
    print("READER", name)
    reader:take()
    for  i, temp in ipairs(reader.samples) do

        print("\t id:", temp['id']) -- key

        if (not reader.infos[i].valid_data) then
            print("\t invalid data!")
        end

        print("\t location:", temp['location'])
        print("\t temperature:", temp['temperature'])

    end
end

Ran Prototyper:

./lib/armv6vfphLinux3.xgcc4.7.2/rtiddsprototyper \
  -cfgFile TempMonitor.xml \
  -cfgName MyParticipantLibrary::TempMonitorSub \
  -luaFile TempMonitor.lua

will print on the screen the values:

READER     MySubscriber::TempReader
  	id:     28.AE01EF020000
  	location: 	gp-cube
     temperature:       71.712501525879

Altered the Lua script to push the data to the cloud instead of printing it on the screen:

local appId  = "A0qMAbHhYCMwG0LzH639yxXeWVKEzH**********"
local appKey = "CIt8kzBXI6FnLTNwqDrwLXBmlvOSLc**********"

-- Iterate over all the readers
for name,reader in pairs(CONTAINER.READER) do

    print("READER", name)
    reader:take()

    for  i, temp in ipairs(reader.samples) do

        if (reader.infos[i].valid_data) then
            os.execute(string.format("curl -X POST   -H \"X-Parse
               -Application-Id: %s\"   -H \"X-Parse-REST-API-Key:
                %s\"   -H \"Content-Type: application/json\"   -d
                '{\"id\":\"%s\",\"location\":\"%s\",\"temperature\":%f}'
                https://api.parse.com/1/classes/TempSamples",
                appId,appKey,temp['id'],temp['location'],temp['temperature']))
        end
    end
end

That's it! Here a screenshot of the data populating the database:

Data populating the database

Don't forget your iPhone

With a few modifications to a basic example iphone application downloaded from parse.com, we ended up with:

gp_iphoneScreen

Get the application source code in GitHub.

Conclusion

It turned out that the northwest corner is indeed colder than the engineering side, but sadly, we could not demonstrate that is due to engineers being hot. If you are an engineer and you're looking for a job or an internship, you can come to RTI and find out for yourself! Have a look at our openings here.

Questions? Trying to explore further possibilities?

Share your Connext DDS adventures with the RTI Community or email lua@rti.com. Also be sure to download the latest version of Connext DDS, complete with RTI Prototyper.

30-day Free Trial

Let Us Know What You Thought of the Article.

Leave a Comment Below.

Subscribe to Email Updates