Graphics.ASimpleDCOMMLightClient - lordmundi/wikidoctest GitHub Wiki

A Simple DCOMM Light Client

« DCOMM Settings | EDGE User’s Guide | Driving Flags Over DCOMM »

DCOMM is a library which can be used to communicate to an instance of DOUG. It is what is used for all of the EDGE clients to sync automatically with the EDGE manager (which is the DCOMM server).

These EDGE clients which have a full graphics tree local to each instance are known as "Full" clients. That is, they have their own copy of the tree and DCOMM is used to keep it in sync with the manager, which keeps all other clients in sync as well.

The other type of client is a light client. For example, if you have a small C program that wants to communicate with the EDGE manager, you will not have a copy of the entire tree - you will just connect and probably manipulate a certain node by name.

The following is an example client that shows the initialization as well as the driving of a node. Note that light clients "register" nodes they are interested in with the server using the DCF_GetNodeID call. Once they get a node ID from the server, the server remembers that it is a node that they care about.

A client like this is common for simulations that wish to drive data to graphics.

It is important to note that the following code serves two purposes: (1) to serve as a light client example as described above and (2) to serve as an example of how to initialize a DCOMM connection to the manager with a timeout. This is discussed in the code.

#include <stdio.h>
#include "dsp.h"
#include "d_comm.h"

extern DCS_CLIENT * DCV_client;

int main() {
    double pos[3] = {3.0, -10.0, 10.0};
    char* node_name = "JIMBO_RMS";
    int node_id = -2;
    int done = 0;
    int mgr_available = 0;
    double timeout = 2.0;
    int comm_success;

    // Init method 1
    // This is the short, simple way to initialize - one call to DCF_InitProc().  It
    // will block here until it detects a matching manager and connects.  If
    // you want more control over detection of the server and timeouts, then use
    // the alternate method below
    //DCF_InitProc();

    // init method 2
    if( DCF_InitClient( 1 , DCD_LIGHT_CLIENT ) < 0 ) { fprintf(stderr, "ERROR initializing client\n"); return -1; }
    if( DCF_ReadConfig( &(DCV_client->config) , NULL ) < 0 ) { fprintf(stderr, "ERROR reading config\n"); return -1; }
    while (!done) {
        mgr_available = DCF_ClientConnectionAvailable( timeout );
        if (mgr_available == 0) {
            done = 0;
            usleep(5000000);
        } else if (mgr_available == 1) {
            done = 1;
            fprintf(stderr, "Manager detected! Connecting...\n");
        } else if (mgr_available < 0) {
            fprintf(stderr, "ERROR checking for connection available.\n");
            return -1;
        }
    }
    if( DCF_ClientConnect() < 0 ) { fprintf(stderr, "ERROR Connecting\n"); return -1; }

    // end init

    DCF_Client();
    node_id = DCF_GetNodeID(node_name);
    //fprintf(stderr, "Node id for %s came back as %d\n", node_name, node_id);

    while (1) {

        pos[0] += 0.5;
        DCF_SetPosD(node_id, pos);
        //fprintf(stderr, "Updating node %s to pos.x %.2f\n", node_name, pos[0]);

        comm_success = DCF_Client();
        if (comm_success < 0) {
            fprintf(stderr, "Error communicating with server.\n");
            return -1;
        }
        usleep(5000000);  // the main sleep for our loop
    }

    return 0;
}

For building the code on linux or mac, ultimately you would just have a gcc line that includes in the header directories needed (which for EDGE v2.3 are all in src.dist/includes or for v2.4 are in a couple of different directories). Then, for linking, the gcc line would link in the dcomm and dsp libraries. That's really it. The below Makefile is an example you can use. It looks a little complicated to support linux or mac and also support different EDGE versions but ultimately, it's pretty simple:

Makefile:

# You can override CPU or HOST_TYPE by
# setting them in your environment first.

CPU         ?= $(shell uname -m)
HOST_TYPE   ?= $(shell uname)

LD_FLAGS = -ld_comm_tc -ldsp -lpthread -ldl -lm
CFLAGS = -g

ifndef DOUG_HOME
    $(error DOUG_HOME is not defined)
endif


ifeq (${CPU},x86_64)
   SUFFIX = _x86_64
   CFLAGS += -m64
   LD_FLAGS += -m64
else
   SUFFIX =
   CFLAGS += -m32
   LD_FLAGS += -m32
endif

ifeq ($(HOST_TYPE),Darwin)
   HOST_CPU    ?= Darwin
   SUFFIX       =
   ifeq (${CPU},x86_64)
       LD_FLAGS    += -lsigar-universal64-macosx
   else
       LD_FLAGS    += -lsigar-universal-macosx
   endif
else ifeq ($(HOST_TYPE),Linux)
   HOST_CPU    ?= Linux_FC3
   HOST_CPU_24 ?= Linux
endif
LIBDIR  = -L${DOUG_HOME}/lib_${HOST_CPU}${SUFFIX}
LIBDIR += -L${DOUG_HOME}/lib_${HOST_CPU_24}${SUFFIX}

INCLUDES       = -I${DOUG_HOME}/src.dist/includes
INCLUDES      += -I${DOUG_HOME}/include
INCLUDES      += -I${DOUG_HOME}/src/tcl8.6.6/generic
INCLUDES      += -I${DOUG_HOME}/src/tk8.6.6/generic

$(info Setting LIBDIR to:      ${LIBDIR})
$(info Setting INCLUDES to:    ${INCLUDES})

all: dcomm_test

clean:
    rm -f dcomm_test dcomm_test.o

dcomm_test: dcomm_test.o
    gcc ${LIBDIR} dcomm_test.o ${LD_FLAGS} -o dcomm_test

dcomm_test.o: dcomm_test.c
    gcc ${INCLUDES} ${CFLAGS} -c dcomm_test.c

An example environment for running the above client might look like:

setenv DOUG_HOME ~/dev/edge

# Adjust to match your setup 
setenv MC_TAG cev_comm_${USER}
setenv MC_PORT 12349
setenv MC_GROUP 225.0.0.48

NOTE: There is also a DCOMM Guide / Function Reference document available in the documents section here.

Usernote: When I tried using this code, I set the MC_PORT and MC_GROUP to be what DOUG wrote to the terminal at runtime:

Multicast RCS is listening at . . .

group: 225.0.0.142
  port:  5552
  tag:   cev_comm_mghart

You do NOT want to set your environment with MC_PORT="5552" and MC_GROUP="225.0.0.142". That doesn't work. Keep MC_PORT at 12349 and MC_GROUP at 225.0.0.48 for this sample code to work.

frankie May 12, 2017, at 02:49 PM: Yes, that is correct. That information is the group and port for the Remote Commanding Server and not DCOMM. To see what the MC_TAG and MC_GROUP and MC_PORT are set to in your doug manager, you can either check the value of the environment variables, or you can run the manager with the "-noquiet" flag and in the output you will see DCOMM report what it is using for these values. —FG

« DCOMM Settings | EDGE User’s Guide | Driving Flags Over DCOMM »

⚠️ **GitHub.com Fallback** ⚠️