Menu

Specifying a remote BBMD?

2014-10-27
2014-10-27
  • Stuart Longland

    Stuart Longland - 2014-10-27

    Hi all,

    We recently developed a MacroView SCADA driver that uses the BacNET stack code, allowing us to poll BMS meters in MacroView. Until now we've only ever used this on a subnet that has a BMS controller on the same subnet.

    Now we've got a situation where I need to talk to a BMS controller from an isolated (at layer 2) subnet. I can ping the destination BMS controller, but as there are different subnets involved, it does not see my broadcast traffic.

    At this time my code does a WHOIS for the device it wishes to communicate with, then uses that to issue its requests. If something is on the same subnet that can reply, I usually get a response back from the WHOIS, and all is good.

    I understand the way to make this work over different subnets is using a BBMD. I've tried setting BACNET_BBMD_ADDRESS to the controller's IP, but tcpdump suggests bacnet-stack is still blindly trying to poll the local broadcast address.

    What steps are necessary to communicate with the remote controller?

    Regards,
    Stuart Longland

     
  • Stuart Longland

    Stuart Longland - 2014-10-27

    I just found this buried in demo/handler/dlenv.c

    /** Register as a Foreign Device with the designated BBMD.
     * @ingroup DataLink
     * The BBMD's address, port, and lease time must be provided by
     * internal variables or Environment variables.
     * If no address for the BBMD is provided, no BBMD registration will occur.
     *
     * The Environment Variables depend on define of BACDL_BIP:
     *     - BACNET_BBMD_PORT - 0..65534, defaults to 47808
     *     - BACNET_BBMD_TIMETOLIVE - 0..65535 seconds, defaults to 60000
     *     - BACNET_BBMD_ADDRESS - dotted IPv4 address
     * @return Positive number (of bytes sent) on success,
     *         0 if no registration request is sent, or
     *         -1 if registration fails.
     */
    int dlenv_register_as_foreign_device(
        void)
    {
        int retval = 0;
    #if defined(BACDL_BIP)
        char *pEnv = NULL;
    
        pEnv = getenv("BACNET_BBMD_PORT");
        if (pEnv) {
            bbmd_port = strtol(pEnv, NULL, 0);
            if (bbmd_port > 0xFFFF) {
                bbmd_port = 0xBAC0;
            }
        }
        pEnv = getenv("BACNET_BBMD_TIMETOLIVE");
        if (pEnv) {
            bbmd_timetolive_seconds = strtol(pEnv, NULL, 0);
            if (bbmd_timetolive_seconds > 0xFFFF) {
                bbmd_timetolive_seconds = 0xFFFF;
            }
        }
        pEnv = getenv("BACNET_BBMD_ADDRESS");
        if (pEnv) {
            bbmd_address = bip_getaddrbyname(pEnv);
        }
        if (bbmd_address) {
            struct in_addr addr;
            addr.s_addr = bbmd_address;
            fprintf(stderr, "Registering with BBMD at %s:%ld for %ld seconds\n",
                inet_ntoa(addr), bbmd_port, bbmd_timetolive_seconds);
            retval =
                bvlc_register_with_bbmd(bbmd_address, htons((uint16_t) bbmd_port),
                (uint16_t) bbmd_timetolive_seconds);
            if (retval < 0)
                fprintf(stderr, "FAILED to Register with BBMD at %s \n",
                    inet_ntoa(addr));
            BBMD_Timer_Seconds = (uint16_t) bbmd_timetolive_seconds;
        }
    
        bbmd_result = retval;
    #endif
        return retval;
    }
    

    I take it those are the magical steps I need to take?

     
  • Stuart Longland

    Stuart Longland - 2014-10-27

    Okay, I think I can call this resolved. I've implemented the necessary options and rolled out an updated driver with BBMD support.

    tcpdump reports packets going to that BBMD. If others are wondering, the above code is how the demos do it.

     

Log in to post a comment.