Example #1
0
int BacnetBindToDevice(
    int deviceInstanceNumber)
{
    int isFailure = 0;

    /* Store the requested device instance number in the global variable for */
    /* reference in other communication routines */
    Target_Device_Object_Instance = deviceInstanceNumber;

    /* try to bind with the device */
    if (!address_bind_request(deviceInstanceNumber, &Target_Max_APDU,
            &Target_Address)) {
        Send_WhoIs(Target_Device_Object_Instance,
            Target_Device_Object_Instance);

        /* Wait for timeout, failure, or success */
        Wait_For_Answer_Or_Timeout(100, waitBind);
    }
    /* Clean up after ourselves */
    isFailure = Error_Detected;
    Error_Detected = false;
    return isFailure;
}
/* It should be called periodically (example once per minute). */
void Notification_Class_find_recipient(
    void)
{
    NOTIFICATION_CLASS_INFO *CurrentNotify;
    BACNET_DESTINATION *pBacDest;
    BACNET_ADDRESS src = { 0 };
    unsigned max_apdu = 0;
    uint32_t notify_index;
    uint32_t DeviceID;
    uint8_t idx;


    for (notify_index = 0; notify_index < MAX_NOTIFICATION_CLASSES;
        notify_index++) {
        /* pointer to current notification */
        CurrentNotify =
            &NC_Info[Notification_Class_Instance_To_Index(notify_index)];
        /* pointer to first recipient */
        pBacDest = &CurrentNotify->Recipient_List[0];
        for (idx = 0; idx < NC_MAX_RECIPIENTS; idx++, pBacDest++) {
            if (CurrentNotify->Recipient_List[idx].Recipient.RecipientType ==
                RECIPIENT_TYPE_DEVICE) {
                /* Device ID */
                DeviceID =
                    CurrentNotify->Recipient_List[idx].Recipient._.
                    DeviceIdentifier;
                /* Send who_ is request only when address of device is unknown. */
                if (!address_bind_request(DeviceID, &max_apdu, &src))
                    Send_WhoIs(DeviceID, DeviceID);
            } else if (CurrentNotify->Recipient_List[idx].Recipient.
                RecipientType == RECIPIENT_TYPE_ADDRESS) {

            }
        }
    }
}
Example #3
0
static void Wait_For_Answer_Or_Timeout(
    unsigned timeout_ms,
    waitAction action)
{
    /* Wait for timeout, failure, or success */
    time_t last_seconds = time(NULL);
    time_t timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
    time_t elapsed_seconds = 0;
    uint16_t pdu_len = 0;
    BACNET_ADDRESS src = { 0 }; /* address where message came from */
    uint8_t Rx_Buf[MAX_MPDU] = { 0 };

    while (true) {
        time_t current_seconds = time(NULL);

        /* If error was detected then bail out */
        if (Error_Detected) {
            LogError("Some other error occurred");
            break;
        }

        if (elapsed_seconds > timeout_seconds) {
            LogError("APDU Timeout");
            break;
        }

        /* Process PDU if one comes in */
        pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout_ms);
        if (pdu_len) {
            npdu_handler(&src, &Rx_Buf[0], pdu_len);
        }

        /* at least one second has passed */
        if (current_seconds != last_seconds) {
            tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
        }

        if (action == waitAnswer) {
            /* Response was received. Exit. */
            if (tsm_invoke_id_free(Request_Invoke_ID)) {
                break;
            } else if (tsm_invoke_id_failed(Request_Invoke_ID)) {
                LogError("TSM Timeout!");
                tsm_free_invoke_id(Request_Invoke_ID);
                break;
            }
        } else if (action == waitBind) {
            if (address_bind_request(Target_Device_Object_Instance,
                    &Target_Max_APDU, &Target_Address)) {
                break;
            }
        } else {
            LogError("Invalid waitAction requested");
            break;
        }

        /* Keep track of time */
        elapsed_seconds += (current_seconds - last_seconds);
        last_seconds = current_seconds;
    }
}
Example #4
0
int main(
    int argc,
    char *argv[])
{
    BACNET_ADDRESS src = {
        0
    };  /* address where message came from */
    uint16_t pdu_len = 0;
    unsigned timeout = 10;      /* milliseconds */
    unsigned max_apdu = 0;
    time_t elapsed_seconds = 0;
    time_t last_seconds = 0;
    time_t current_seconds = 0;
    time_t timeout_seconds = 0;
    time_t delta_seconds = 0;
    bool found = false;
    char *filename = NULL;
    char *value_string = NULL;
    bool status = false;
    int args_remaining = 0, tag_value_arg = 0, i = 0;
    BACNET_APPLICATION_TAG property_tag;
    uint8_t context_tag = 0;
    BACNET_PRIVATE_TRANSFER_DATA private_data = { 0 };
    int len = 0;
    bool sent_message = false;

    if (argc < 6) {
        filename = filename_remove_path(argv[0]);
        printf("Usage: %s <device-instance|broadcast|dnet=> vendor-id"
            " service-number tag value [tag value...]\r\n", filename);
        if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
            printf("device-instance:\r\n"
                "BACnet Device Object Instance number that you are\r\n"
                "trying to communicate to.  This number will be used\r\n"
                "to try and bind with the device using Who-Is and\r\n"
                "I-Am services.  For example, if you were transferring to\r\n"
                "Device Object 123, the device-instance would be 123.\r\n"
                "For Global Broadcast, use the word 'broadcast'.\r\n"
                "For Local Broadcast to a particular DNET n, use 'dnet=n'.\r\n"
                "\r\n" "vendor_id:\r\n"
                "the unique vendor identification code for the type of\r\n"
                "vendor proprietary service to be performed.\r\n" "\r\n"
                "service-number (Unsigned32):\r\n"
                "the desired proprietary service to be performed.\r\n" "\r\n"
                "tag:\r\n" "Tag is the integer value of the enumeration \r\n"
                "BACNET_APPLICATION_TAG in bacenum.h.\r\n"
                "It is the data type of the value that you are sending.\r\n"
                "For example, if you were transfering a REAL value, you would \r\n"
                "use a tag of 4.\r\n"
                "Context tags are created using two tags in a row.\r\n"
                "The context tag is preceded by a C.  Ctag tag.\r\n"
                "C2 4 creates a context 2 tagged REAL.\r\n" "\r\n" "value:\r\n"
                "The value is an ASCII representation of some type of data\r\n"
                "that you are transfering.\r\n"
                "It is encoded using the tag information provided.\r\n"
                "For example, if you were transferring a REAL value of 100.0,\r\n"
                "you would use 100.0 as the value.\r\n"
                "If you were transferring an object identifier for Device 123,\r\n"
                "you would use 8:123 as the value.\r\n" "\r\n" "Example:\r\n"
                "If you want to transfer a REAL value of 1.1 to service 23 of \r\n"
                "vendor 260 in Device 99, you could send the following command:\r\n"
                "%s 99 260 23 4 1.1\r\n", filename);
        }
        return 0;
    }
    /* decode the command line parameters */
    if (strcmp(argv[1], "broadcast") == 0) {
        Target_Broadcast = true;
        Target_DNET = BACNET_BROADCAST_NETWORK;
    } else if (strncmp(argv[1], "dnet=", 5) == 0) {
        Target_Broadcast = true;
        Target_DNET = strtol(&argv[1][5], NULL, 0);
    } else {
        Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
    }
    Target_Vendor_Identifier = strtol(argv[2], NULL, 0);
    Target_Service_Number = strtol(argv[3], NULL, 0);
    if ((!Target_Broadcast) &&
        (Target_Device_Object_Instance > BACNET_MAX_INSTANCE)) {
        fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
            Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
        return 1;
    }
    args_remaining = (argc - (6 - 2));
    for (i = 0; i < MAX_PROPERTY_VALUES; i++) {
        tag_value_arg = (6 - 2) + (i * 2);
        /* special case for context tagged values */
        if (toupper(argv[tag_value_arg][0]) == 'C') {
            context_tag = strtol(&argv[tag_value_arg][1], NULL, 0);
            tag_value_arg++;
            args_remaining--;
            Target_Object_Property_Value[i].context_tag = context_tag;
            Target_Object_Property_Value[i].context_specific = true;
        } else {
            Target_Object_Property_Value[i].context_specific = false;
        }
        property_tag = strtol(argv[tag_value_arg], NULL, 0);
        args_remaining--;
        if (args_remaining <= 0) {
            fprintf(stderr, "Error: not enough tag-value pairs\r\n");
            return 1;
        }
        value_string = argv[tag_value_arg + 1];
        args_remaining--;
        /* printf("tag[%d]=%u value[%d]=%s\r\n",
           i, property_tag, i, value_string); */
        if (property_tag >= MAX_BACNET_APPLICATION_TAG) {
            fprintf(stderr, "Error: tag=%u - it must be less than %u\r\n",
                property_tag, MAX_BACNET_APPLICATION_TAG);
            return 1;
        }
        status =
            bacapp_parse_application_data(property_tag, value_string,
            &Target_Object_Property_Value[i]);
        if (!status) {
            /* FIXME: show the expected entry format for the tag */
            fprintf(stderr, "Error: unable to parse the tag value\r\n");
            return 1;
        }
        Target_Object_Property_Value[i].next = NULL;
        if (i > 0) {
            Target_Object_Property_Value[i - 1].next =
                &Target_Object_Property_Value[i];
        }
        if (args_remaining <= 0) {
            break;
        }
    }
    if (args_remaining > 0) {
        fprintf(stderr, "Error: Exceeded %d tag-value pairs.\r\n",
            MAX_PROPERTY_VALUES);
        return 1;
    }
    /* setup my info */
    Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
    address_init();
    Init_Service_Handlers();
    dlenv_init();
    atexit(datalink_cleanup);
    /* configure the timeout values */
    last_seconds = time(NULL);
    if (Target_Broadcast) {
        datalink_get_broadcast_address(&Target_Address);
        Target_Address.net = Target_DNET;
        found = true;
        timeout_seconds = 0;
    } else {
        timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
        /* try to bind with the device */
        found =
            address_bind_request(Target_Device_Object_Instance, &max_apdu,
            &Target_Address);
        if (!found) {
            Send_WhoIs(Target_Device_Object_Instance,
                Target_Device_Object_Instance);
        }
    }
    /* loop forever */
    for (;;) {
        /* increment timer - exit if timed out */
        current_seconds = time(NULL);
        /* at least one second has passed */
        if (current_seconds != last_seconds) {
            /* increment timer - exit if timed out */
            delta_seconds = current_seconds - last_seconds;
            elapsed_seconds += delta_seconds;
            tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
        }
        if (Error_Detected)
            break;
        /* wait until the device is bound, or timeout and quit */
        if (!found) {
            found =
                address_bind_request(Target_Device_Object_Instance, &max_apdu,
                &Target_Address);
        }
        if (!sent_message) {
            if (found) {
                len =
                    bacapp_encode_data(&Service_Parameters[0],
                    &Target_Object_Property_Value[0]);
                private_data.serviceParameters = &Service_Parameters[0];
                private_data.serviceParametersLen = len;
                private_data.vendorID = Target_Vendor_Identifier;
                private_data.serviceNumber = Target_Service_Number;
                Send_UnconfirmedPrivateTransfer(&Target_Address,
                    &private_data);
                printf("Sent PrivateTransfer.");
                if (timeout_seconds) {
                    printf(" Waiting %u seconds.\r\n",
                        (unsigned) (timeout_seconds - elapsed_seconds));
                } else {
                    printf("\r\n");
                }
                sent_message = true;
            } else {
                if (elapsed_seconds > timeout_seconds) {
                    printf("\rError: APDU Timeout!\r\n");
                    Error_Detected = true;
                    break;
                }
            }
        }
        /* returns 0 bytes on timeout */
        pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
        /* process */
        if (pdu_len) {
            npdu_handler(&src, &Rx_Buf[0], pdu_len);
        }
        if (Error_Detected) {
            break;
        }
        /* unconfirmed - so just wait until our timeout value */
        if (elapsed_seconds > timeout_seconds) {
            break;
        }
        /* keep track of time for next check */
        last_seconds = current_seconds;
    }

    if (Error_Detected)
        return 1;
    return 0;
}
Example #5
0
int main(
    int argc,
    char *argv[])
{
    BACNET_ADDRESS src = {
        0
    };  /* address where message came from */
    uint16_t pdu_len = 0;
    unsigned timeout = 100;     /* milliseconds */
    unsigned max_apdu = 0;
    time_t elapsed_seconds = 0;
    time_t last_seconds = 0;
    time_t current_seconds = 0;
    time_t timeout_seconds = 0;
    uint8_t invoke_id = 0;
    bool found = false;
    DATABLOCK NewData;
    int iCount = 0;
    int iType = 0;
    int iKey;

    if (((argc != 2) && (argc != 3)) || ((argc >= 2) &&
            (strcmp(argv[1], "--help") == 0))) {
        printf("%s\n", argv[0]);
        printf("Usage: %s server local-device-instance\r\n       or\r\n"
            "       %s remote-device-instance\r\n",
            filename_remove_path(argv[0]), filename_remove_path(argv[0]));
        if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
            printf("\r\nServer mode:\r\n\r\n"
                "local-device-instance determins the device id of the application\r\n"
                "when running as the server end of a test set up.\r\n\r\n"
                "Non server:\r\n\r\n"
                "remote-device-instance indicates the device id of the server\r\n"
                "instance of the application.\r\n"
                "The non server application will write a series of blocks to the\r\n"
                "server and then retrieve them for display locally\r\n"
                "First it writes all 8 blocks plus a 9th which should trigger\r\n"
                "an out of range error response. Then it reads all the blocks\r\n"
                "including the ninth and finally it repeats the read operation\r\n"
                "with some deliberate errors to trigger a nack response\r\n");
        }
        return 0;
    }
    /* decode the command line parameters */
    if (_stricmp(argv[1], "server") == 0)
        Target_Mode = 1;
    else
        Target_Mode = 0;

    Target_Device_Object_Instance = strtol(argv[1 + Target_Mode], NULL, 0);

    if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
        fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
            Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
        return 1;
    }

    /* setup my info */
    if (Target_Mode)
        Device_Set_Object_Instance_Number(Target_Device_Object_Instance);
    else
        Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);

    address_init();
    Init_Service_Handlers();
    dlenv_init();
    atexit(datalink_cleanup);
    /* configure the timeout values */
    last_seconds = time(NULL);
    timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();

    if (Target_Mode) {
        printf("Entering server mode. press q to quit program\r\n\r\n");

        for (;;) {
            /* increment timer - exit if timed out */
            current_seconds = time(NULL);
            if (current_seconds != last_seconds) {
            }

            /* returns 0 bytes on timeout */
            pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);

            /* process */
            if (pdu_len) {
                npdu_handler(&src, &Rx_Buf[0], pdu_len);
            }
            /* at least one second has passed */
            if (current_seconds != last_seconds) {
                putchar('.');   /* Just to show that time is passing... */
                last_seconds = current_seconds;
                tsm_timer_milliseconds(((current_seconds -
                            last_seconds) * 1000));
            }

            if (_kbhit()) {
                iKey = toupper(_getch());
                if (iKey == 'Q') {
                    printf("\r\nExiting program now\r\n");
                    exit(0);
                }
            }
        }
    } else {

        /* try to bind with the device */
        found =
            address_bind_request(Target_Device_Object_Instance, &max_apdu,
            &Target_Address);
        if (!found) {
            Send_WhoIs(Target_Device_Object_Instance,
                Target_Device_Object_Instance);
        }
        /* loop forever */
        for (;;) {
            /* increment timer - exit if timed out */
            current_seconds = time(NULL);

            /* returns 0 bytes on timeout */
            pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);

            /* process */
            if (pdu_len) {
                npdu_handler(&src, &Rx_Buf[0], pdu_len);
            }
            /* at least one second has passed */
            if (current_seconds != last_seconds)
                tsm_timer_milliseconds(((current_seconds -
                            last_seconds) * 1000));
            if (Error_Detected)
                break;
            /* wait until the device is bound, or timeout and quit */
            if (!found)
                found =
                    address_bind_request(Target_Device_Object_Instance,
                    &max_apdu, &Target_Address);
            if (found) {
                if (invoke_id == 0) {   /* Safe to send a new request */
                    switch (iType) {
                        case 0:        /* Write blocks to server */
                            NewData.cMyByte1 = iCount;
                            NewData.cMyByte2 = 255 - iCount;
                            NewData.fMyReal = (float) iCount;
                            strcpy((char*)NewData.sMyString, "Test Data - [x]");
                            NewData.sMyString[13] = 'a' + iCount;
                            printf("Sending block %d\n", iCount);
                            invoke_id =
                                Send_Private_Transfer_Request
                                (Target_Device_Object_Instance,
                                BACNET_VENDOR_ID, 1, iCount, &NewData);
                            break;

                        case 1:        /* Read blocks from server */
                            printf("Requesting block %d\n", iCount);
                            invoke_id =
                                Send_Private_Transfer_Request
                                (Target_Device_Object_Instance,
                                BACNET_VENDOR_ID, 0, iCount, &NewData);
                            break;

                        case 2:        /* Generate some error responses */
                            switch (iCount) {
                                case 0:        /* Bad service number i.e. 2 */
                                case 2:
                                case 4:
                                case 6:
                                case 8:
                                    printf
                                        ("Requesting block %d with bad service number\n",
                                        iCount);
                                    invoke_id =
                                        Send_Private_Transfer_Request
                                        (Target_Device_Object_Instance,
                                        BACNET_VENDOR_ID, 2, iCount, &NewData);
                                    break;

                                case 1:        /* Bad vendor ID number */
                                case 3:
                                case 5:
                                case 7:
                                    printf
                                        ("Requesting block %d with invalid Vendor ID\n",
                                        iCount);
                                    invoke_id =
                                        Send_Private_Transfer_Request
                                        (Target_Device_Object_Instance,
                                        BACNET_VENDOR_ID + 1, 0, iCount,
                                        &NewData);
                                    break;
                            }

                            break;
                    }
                } else if (tsm_invoke_id_free(invoke_id)) {
                    if (iCount != MY_MAX_BLOCK) {
                        iCount++;
                        invoke_id = 0;
                    } else {
                        iType++;
                        iCount = 0;
                        invoke_id = 0;

                        if (iType > 2)
                            break;
                    }
                } else if (tsm_invoke_id_failed(invoke_id)) {
                    fprintf(stderr, "\rError: TSM Timeout!\r\n");
                    tsm_free_invoke_id(invoke_id);
                    Error_Detected = true;
                    /* try again or abort? */
                    break;
                }
            } else {
                /* increment timer - exit if timed out */
                elapsed_seconds += (current_seconds - last_seconds);
                if (elapsed_seconds > timeout_seconds) {
                    printf("\rError: APDU Timeout!\r\n");
                    Error_Detected = true;
                    break;
                }
            }
            /* keep track of time for next check */
            last_seconds = current_seconds;
        }
    }
    if (Error_Detected)
        return 1;
    return 0;
}
Example #6
0
int write_bacnet_obj(bacnet_device_t *device, int obj_index, char *value)
{
    uint8_t rx_buf[MAX_MPDU] = {0};
    BACNET_ADDRESS src = {
        0
    };  /* address where message came from */
    uint16_t pdu_len = 0;
    unsigned timeout = 500;     /* milliseconds */
    unsigned max_apdu = 0;
    time_t elapsed_seconds = 0;
    time_t last_seconds = 0;
    time_t current_seconds = 0;
    time_t timeout_seconds = 0;
    int status = 0, i;

    // Set Property Tag
    BACNET_APPLICATION_TAG property_tag;
    if (device -> obj_types[obj_index] == OBJECT_BINARY_VALUE)
        property_tag = BACNET_APPLICATION_TAG_ENUMERATED;
    else
        property_tag = BACNET_APPLICATION_TAG_REAL;
    BACNET_APPLICATION_DATA_VALUE target_value;

    for (i = 0; i < MAX_PROPERTY_VALUES; i++) {
        target_value.context_specific = false;

        if (property_tag >= MAX_BACNET_APPLICATION_TAG) {
            fprintf(stderr, "Error: tag=%u - it must be less than %u\r\n",
                    property_tag, MAX_BACNET_APPLICATION_TAG);
            return 1;
        }
        status =
            bacapp_parse_application_data(property_tag, value,
                                          &target_value);
        if (!status) {
            printf("Error: unable to parse the tag value\r\n");
            return 1;
        }
        target_value.next = NULL;
        break;
    }

    /* configure the timeout values */
    last_seconds = time(NULL);
    timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();

    /* try to bind with the device */
    found =
        address_bind_request(device -> instance, &max_apdu, &target_address);

    if (!found) {
        Send_WhoIs(device -> instance, device -> instance);
    }
    /* loop forever */
    request_invoke_id = 0;
    while (1) {
        /* increment timer - exit if timed out */
        current_seconds = time(NULL);

        /* at least one second has passed */
        if (current_seconds != last_seconds)
            tsm_timer_milliseconds((uint16_t) ((current_seconds -
                                                last_seconds) * 1000));
        if (error_detected)
            break;
        /* wait until the device is bound, or timeout and quit */
        if (!found) {
            found =
                address_bind_request(device -> instance, &max_apdu,
                                     &target_address);
        }
        if (found) {
            if (request_invoke_id == 0) {
                printf("request invoke set\n");
                write_acked = 0;
                request_invoke_id =
                    Send_Write_Property_Request(device -> instance,
                                                device -> obj_types[obj_index], device -> obj_ids[obj_index],
                                                PROP_PRESENT_VALUE, &target_value,
                                                MESSAGE_PRIORITY_NORMAL, -1);
            } else if (tsm_invoke_id_free(request_invoke_id))
                break;
            else if (tsm_invoke_id_failed(request_invoke_id)) {
                fprintf(stderr, "\rError: TSM Timeout!\r\n");
                tsm_free_invoke_id(request_invoke_id);
                error_detected = true;
                break;
            }
        } else {
            /* increment timer - exit if timed out */
            elapsed_seconds += (current_seconds - last_seconds);
            if (elapsed_seconds > timeout_seconds) {
                error_detected = true;
                printf("\rError: APDU Timeout!\r\n");
                break;
            }
        }

        /* returns 0 bytes on timeout */
        pdu_len = datalink_receive(&src, &rx_buf[0], MAX_MPDU, timeout);

        /* process */
        if (pdu_len) {
            npdu_handler(&src, &rx_buf[0], pdu_len);
        }

        /* keep track of time for next check */
        last_seconds = current_seconds;
    }
    if (error_detected)
    {
        error_detected = 0;
        return 1;
    }
    return 0;
}
Example #7
0
int publish_data(adapter_t *adapter)
{
    static uint8_t rx_buf[MAX_MPDU] = {0};
    bacnet_context_t *context = (bacnet_context_t*) (adapter -> context);
    bacnet_device_t *device;
    time_t current_seconds, elapsed_seconds = 0;
    int pdu_len;
    char *time_str, *node_id;
    time_t last_seconds,timeout_seconds;
    unsigned timeout = 100;
    BACNET_ADDRESS  src = { 0 };
    unsigned max_apdu = 0;
    mio_stanza_t *item;
    mio_response_t *publish_response;
    for (device = context -> node_devices; device; device = device -> nodemap.next)
    {
        time_str = mio_timestamp_create();
        item = mio_pubsub_item_data_new(adapter -> connection);
        node_id = device -> node_id;

        last_seconds = time(NULL);
        timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
        //if (!found)
        found =
            address_bind_request(device -> instance, &max_apdu,
                                 &target_address);
        if (!found)
        {
            Send_WhoIs(device -> instance, device -> instance);
        }
        while (!found)
        {
            current_seconds = time(NULL);
            if (current_seconds != last_seconds)
                tsm_timer_milliseconds((uint16_t) ((current_seconds -
                                                    last_seconds) * 1000));
            if (!found)
            {
                found =
                    address_bind_request(device -> instance,
                                         &max_apdu,&target_address);
            }
            if (!found)
            {
                elapsed_seconds += (current_seconds - last_seconds);
                if (elapsed_seconds > timeout_seconds) {
                    printf("\rError: APDU Timeout!\r\n");
                    return 1;
                }
            }
            pdu_len = datalink_receive(&src, &rx_buf[0], MAX_MPDU,timeout);
            if (pdu_len) {
                npdu_handler(&src, &rx_buf[0], pdu_len);
            }
            last_seconds = current_seconds;
        }
        int i;
        printf("n_objects %d\n", device -> n_objects);
        for ( i = 0; i < device -> n_objects; i++)
        {
            request_invoke_id = 0;
            while(TRUE)
            {
                printf("true\n");
                if (found)
                {
                    if (request_invoke_id == 0)
                    {
                        request_invoke_id =
                            Send_Read_Property_Request(
                                device->instance, device -> obj_types[i],
                                device -> obj_ids[i], 85,
                                -1);
                    } else if (tsm_invoke_id_free(request_invoke_id))
                        break;
                    else if (tsm_invoke_id_failed(request_invoke_id))
                    {
                        fprintf(stderr,"\rError: TSM Timeout!\r\n");
                        tsm_free_invoke_id(request_invoke_id);
                        return 1;
                    }
                }
                pdu_len = datalink_receive(&src, &rx_buf[0], MAX_MPDU,timeout);
                if (pdu_len) {
                    npdu_handler(&src, &rx_buf[0], pdu_len);
                }
                last_seconds = current_seconds;
            }
            if (error_detected)
            {
                error_detected = 0;
                return 1;
            } else
            {
                if (strcmp(value,"active") == 0)
                    mio_item_transducer_value_add(item, NULL, device -> obj_names[i] , "1", value,  time_str);
                else if (strcmp(value,"inactive") == 0)
                    mio_item_transducer_value_add(item, NULL, device -> obj_names[i] , "0",value,  time_str);
                else
                    mio_item_transducer_value_add(item, NULL, device -> obj_names[i] , value, value, time_str);
            }

        }
        publish_response = mio_response_new();
        while (adapter -> connection -> xmpp_conn -> state != XMPP_STATE_CONNECTED)
            usleep(1000);
        mio_item_publish_data(adapter -> connection,item,node_id,publish_response);
        free(time_str);
        mio_response_print(publish_response);
        mio_response_free(publish_response);
        mio_stanza_free(item);
    }
    return 0;
}
Example #8
0
int main(
    int argc,
    char *argv[])
{
    BACNET_ADDRESS src = {
        0
    };  /* address where message came from */
    uint16_t pdu_len = 0;
    unsigned timeout = 100;     /* milliseconds */
    unsigned max_apdu = 0;
    time_t elapsed_seconds = 0;
    time_t last_seconds = 0;
    time_t current_seconds = 0;
    time_t timeout_seconds = 0;
    bool found = false;
    char *value_string = NULL;
    bool status = false;
    int args_remaining = 0, tag_value_arg = 0, i = 0;
    BACNET_APPLICATION_TAG property_tag;
    uint8_t context_tag = 0;
    int argi = 0;

    /* print help if requested */
    for (argi = 1; argi < argc; argi++) {
        if (strcmp(argv[argi], "--help") == 0) {
            print_usage(filename_remove_path(argv[0]));
            print_help(filename_remove_path(argv[0]));
            return 0;
        }
        if (strcmp(argv[argi], "--version") == 0) {
            printf("%s %s\n",
                filename_remove_path(argv[0]),
                BACNET_VERSION_TEXT);
            printf("Copyright (C) 2014 by Steve Karg\n"
                "This is free software; see the source for copying conditions.\n"
                "There is NO warranty; not even for MERCHANTABILITY or\n"
                "FITNESS FOR A PARTICULAR PURPOSE.\n");
            return 0;
        }
    }
    if (argc < 9) {
        print_usage(filename_remove_path(argv[0]));
        return 0;
    }
    /* decode the command line parameters */
    Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
    Target_Object_Type = strtol(argv[2], NULL, 0);
    Target_Object_Instance = strtol(argv[3], NULL, 0);
    Target_Object_Property = strtol(argv[4], NULL, 0);
    Target_Object_Property_Priority = (uint8_t) strtol(argv[5], NULL, 0);
    Target_Object_Property_Index = strtol(argv[6], NULL, 0);
    if (Target_Object_Property_Index == -1)
        Target_Object_Property_Index = BACNET_ARRAY_ALL;
    if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
        fprintf(stderr, "device-instance=%u - it must be less than %u\n",
            Target_Device_Object_Instance, BACNET_MAX_INSTANCE + 1);
        return 1;
    }
    if (Target_Object_Type > MAX_BACNET_OBJECT_TYPE) {
        fprintf(stderr, "object-type=%u - it must be less than %u\n",
            Target_Object_Type, MAX_BACNET_OBJECT_TYPE + 1);
        return 1;
    }
    if (Target_Object_Instance > BACNET_MAX_INSTANCE) {
        fprintf(stderr, "object-instance=%u - it must be less than %u\n",
            Target_Object_Instance, BACNET_MAX_INSTANCE + 1);
        return 1;
    }
    if (Target_Object_Property > MAX_BACNET_PROPERTY_ID) {
        fprintf(stderr, "property=%u - it must be less than %u\n",
            Target_Object_Property, MAX_BACNET_PROPERTY_ID + 1);
        return 1;
    }
    args_remaining = (argc - 7);
    for (i = 0; i < MAX_PROPERTY_VALUES; i++) {
        tag_value_arg = 7 + (i * 2);
        /* special case for context tagged values */
        if (toupper(argv[tag_value_arg][0]) == 'C') {
            context_tag = (uint8_t) strtol(&argv[tag_value_arg][1], NULL, 0);
            tag_value_arg++;
            args_remaining--;
            Target_Object_Property_Value[i].context_tag = context_tag;
            Target_Object_Property_Value[i].context_specific = true;
        } else {
            Target_Object_Property_Value[i].context_specific = false;
        }
        property_tag = strtol(argv[tag_value_arg], NULL, 0);
        args_remaining--;
        if (args_remaining <= 0) {
            fprintf(stderr, "Error: not enough tag-value pairs\n");
            return 1;
        }
        value_string = argv[tag_value_arg + 1];
        args_remaining--;
        /* printf("tag[%d]=%u value[%d]=%s\n",
           i, property_tag, i, value_string); */
        if (property_tag >= MAX_BACNET_APPLICATION_TAG) {
            fprintf(stderr, "Error: tag=%u - it must be less than %u\n",
                property_tag, MAX_BACNET_APPLICATION_TAG);
            return 1;
        }
        status =
            bacapp_parse_application_data(property_tag, value_string,
            &Target_Object_Property_Value[i]);
        if (!status) {
            /* FIXME: show the expected entry format for the tag */
            fprintf(stderr, "Error: unable to parse the tag value\n");
            return 1;
        }
        Target_Object_Property_Value[i].next = NULL;
        if (i > 0) {
            Target_Object_Property_Value[i - 1].next =
                &Target_Object_Property_Value[i];
        }
        if (args_remaining <= 0) {
            break;
        }
    }
    if (args_remaining > 0) {
        fprintf(stderr, "Error: Exceeded %d tag-value pairs.\n",
            MAX_PROPERTY_VALUES);
        return 1;
    }
    /* setup my info */
    Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
    address_init();
    Init_Service_Handlers();
    dlenv_init();
    atexit(datalink_cleanup);
    /* configure the timeout values */
    last_seconds = time(NULL);
    timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
    /* try to bind with the device */
    found =
        address_bind_request(Target_Device_Object_Instance, &max_apdu,
        &Target_Address);
    if (!found) {
        Send_WhoIs(Target_Device_Object_Instance,
            Target_Device_Object_Instance);
    }
    /* loop forever */
    for (;;) {
        /* increment timer - exit if timed out */
        current_seconds = time(NULL);

        /* at least one second has passed */
        if (current_seconds != last_seconds)
            tsm_timer_milliseconds((uint16_t) ((current_seconds -
                        last_seconds) * 1000));
        if (Error_Detected)
            break;
        /* wait until the device is bound, or timeout and quit */
        if (!found) {
            found =
                address_bind_request(Target_Device_Object_Instance, &max_apdu,
                &Target_Address);
        }
        if (found) {
            if (Request_Invoke_ID == 0) {
                Request_Invoke_ID =
                    Send_Write_Property_Request(Target_Device_Object_Instance,
                    Target_Object_Type, Target_Object_Instance,
                    Target_Object_Property, &Target_Object_Property_Value[0],
                    Target_Object_Property_Priority,
                    Target_Object_Property_Index);
            } else if (tsm_invoke_id_free(Request_Invoke_ID))
                break;
            else if (tsm_invoke_id_failed(Request_Invoke_ID)) {
                fprintf(stderr, "\rError: TSM Timeout!\n");
                tsm_free_invoke_id(Request_Invoke_ID);
                Error_Detected = true;
                /* try again or abort? */
                break;
            }
        } else {
            /* increment timer - exit if timed out */
            elapsed_seconds += (current_seconds - last_seconds);
            if (elapsed_seconds > timeout_seconds) {
                Error_Detected = true;
                printf("\rError: APDU Timeout!\n");
                break;
            }
        }

        /* returns 0 bytes on timeout */
        pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);

        /* process */
        if (pdu_len) {
            npdu_handler(&src, &Rx_Buf[0], pdu_len);
        }

        /* keep track of time for next check */
        last_seconds = current_seconds;
    }
    if (Error_Detected)
        return 1;
    return 0;
}
Example #9
0
int main(
    int argc,
    char *argv[])
{
    BACNET_ADDRESS src = {
        0
    };  /* address where message came from */
    uint16_t pdu_len = 0;
    unsigned timeout = 100;     /* milliseconds */
    unsigned max_apdu = 0;
    time_t elapsed_seconds = 0;
    time_t last_seconds = 0;
    time_t current_seconds = 0;
    time_t timeout_seconds = 0;
    uint8_t invoke_id = 0;
    bool found = false;

    if (argc < 3) {
        printf("Usage: %s device-instance state timeout [password]\r\n"
            "Send BACnet DeviceCommunicationControl service to device.\r\n"
            "\r\n" "The device-instance can be 0 to %d.\r\n"
            "Possible state values:\r\n" "  0=enable\r\n" "  1=disable\r\n"
            "  2=disable-initiation\r\n"
            "The timeout can be 0 for infinite, or a value in minutes for disable.\r\n"
            "The optional password is a character string of 1 to 20 characters.\r\n"
            "Use BACNET_IFACE environment variable for the interface\r\n",
            filename_remove_path(argv[0]), BACNET_MAX_INSTANCE - 1);
        return 0;
    }
    /* decode the command line parameters */
    Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
    Communication_State = (uint16_t) strtol(argv[2], NULL, 0);
    Communication_Timeout_Minutes = (uint16_t) strtol(argv[3], NULL, 0);
    /* optional password */
    if (argc > 4)
        Communication_Password = argv[4];

    if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
        fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
            Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
        return 1;
    }

    /* setup my info */
    Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
    address_init();
    Init_Service_Handlers();
    dlenv_init();
    atexit(datalink_cleanup);
    /* configure the timeout values */
    last_seconds = time(NULL);
    timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
    /* try to bind with the device */
    found =
        address_bind_request(Target_Device_Object_Instance, &max_apdu,
        &Target_Address);
    if (!found) {
        Send_WhoIs(Target_Device_Object_Instance,
            Target_Device_Object_Instance);
    }
    /* loop forever */
    for (;;) {
        /* increment timer - exit if timed out */
        current_seconds = time(NULL);

        /* returns 0 bytes on timeout */
        pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);

        /* process */
        if (pdu_len) {
            npdu_handler(&src, &Rx_Buf[0], pdu_len);
        }
        /* at least one second has passed */
        if (current_seconds != last_seconds)
            tsm_timer_milliseconds((uint16_t) ((current_seconds -
                        last_seconds) * 1000));
        if (Error_Detected)
            break;
        /* wait until the device is bound, or timeout and quit */
        if (!found) {
            found =
                address_bind_request(Target_Device_Object_Instance, &max_apdu,
                &Target_Address);
        }
        if (found) {
            if (invoke_id == 0) {
                invoke_id =
                    Send_Device_Communication_Control_Request
                    (Target_Device_Object_Instance,
                    Communication_Timeout_Minutes, Communication_State,
                    Communication_Password);
            } else if (tsm_invoke_id_free(invoke_id))
                break;
            else if (tsm_invoke_id_failed(invoke_id)) {
                fprintf(stderr, "\rError: TSM Timeout!\r\n");
                tsm_free_invoke_id(invoke_id);
                /* try again or abort? */
                break;
            }
        } else {
            /* increment timer - exit if timed out */
            elapsed_seconds += (current_seconds - last_seconds);
            if (elapsed_seconds > timeout_seconds) {
                printf("\rError: APDU Timeout!\r\n");
                break;
            }
        }
        /* keep track of time for next check */
        last_seconds = current_seconds;
    }

    return 0;
}
Example #10
0
int main(
    int argc,
    char *argv[])
{
    BACNET_ADDRESS src = {
        0
    };  /* address where message came from */
    uint16_t pdu_len = 0;
    unsigned timeout = 100;     /* milliseconds */
    unsigned max_apdu = 0;
    time_t elapsed_seconds = 0;
    time_t last_seconds = 0;
    time_t current_seconds = 0;
    time_t timeout_seconds = 0;
    int fileStartPosition = 0;
    unsigned requestedOctetCount = 0;
    uint8_t invoke_id = 0;
    bool found = false;
    uint16_t my_max_apdu = 0;

    if (argc < 4) {
        /* FIXME: what about access method - record or stream? */
        printf("%s device-instance file-instance local-name\r\n",
            filename_remove_path(argv[0]));
        return 0;
    }
    /* decode the command line parameters */
    Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
    Target_File_Object_Instance = strtol(argv[2], NULL, 0);
    Local_File_Name = argv[3];
    if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
        fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
            Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
        return 1;
    }
    if (Target_File_Object_Instance >= BACNET_MAX_INSTANCE) {
        fprintf(stderr, "file-instance=%u - it must be less than %u\r\n",
            Target_File_Object_Instance, BACNET_MAX_INSTANCE + 1);
        return 1;
    }
    /* setup my info */
    Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
    address_init();
    Init_Service_Handlers();
    dlenv_init();
    atexit(datalink_cleanup);
    /* configure the timeout values */
    last_seconds = time(NULL);
    timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
    /* try to bind with the device */
    Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
    /* loop forever */
    for (;;) {
        /* increment timer - exit if timed out */
        current_seconds = time(NULL);

        /* returns 0 bytes on timeout */
        pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);

        /* process */
        if (pdu_len) {
            npdu_handler(&src, &Rx_Buf[0], pdu_len);
        }
        /* at least one second has passed */
        if (current_seconds != last_seconds) {
            tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
        }
        /* wait until the device is bound, or timeout and quit */
        found =
            address_bind_request(Target_Device_Object_Instance, &max_apdu,
            &Target_Address);
        if (found) {
            /* calculate the smaller of our APDU size or theirs
               and remove the overhead of the APDU (about 16 octets max).
               note: we could fail if there is a bottle neck (router)
               and smaller MPDU in betweeen. */
            if (max_apdu < MAX_APDU) {
                my_max_apdu = max_apdu;
            } else {
                my_max_apdu = MAX_APDU;
            }
            /* Typical sizes are 50, 128, 206, 480, 1024, and 1476 octets */
            if (my_max_apdu <= 50) {
                requestedOctetCount = my_max_apdu - 20;
            } else if (my_max_apdu <= 480) {
                requestedOctetCount = my_max_apdu - 32;
            } else if (my_max_apdu <= 1476) {
                requestedOctetCount = my_max_apdu - 64;
            } else {
                requestedOctetCount = my_max_apdu / 2;
            }
            /* has the previous invoke id expired or returned?
               note: invoke ID = 0 is invalid, so it will be idle */
            if ((invoke_id == 0) || tsm_invoke_id_free(invoke_id)) {
                if (End_Of_File_Detected || Error_Detected) {
                    break;
                }
                if (invoke_id != 0) {
                    fileStartPosition += requestedOctetCount;
                }
                /* we'll read the file in chunks
                   less than max_apdu to keep unsegmented */
                invoke_id =
                    Send_Atomic_Read_File_Stream(Target_Device_Object_Instance,
                    Target_File_Object_Instance, fileStartPosition,
                    requestedOctetCount);
                Current_Invoke_ID = invoke_id;
            } else if (tsm_invoke_id_failed(invoke_id)) {
                fprintf(stderr, "\rError: TSM Timeout!\r\n");
                tsm_free_invoke_id(invoke_id);
                /* try again or abort? */
                Error_Detected = true;
                break;
            }
        } else {
            /* increment timer - exit if timed out */
            elapsed_seconds += (current_seconds - last_seconds);
            if (elapsed_seconds > timeout_seconds) {
                fprintf(stderr, "\rError: APDU Timeout!\r\n");
                Error_Detected = true;
                break;
            }
        }
        /* keep track of time for next check */
        last_seconds = current_seconds;
    }

    if (Error_Detected) {
        return 1;
    }

    return 0;
}
Example #11
0
int main(
    int argc,
    char *argv[])
{
    BACNET_ADDRESS src = {
        0
    };  /* address where message came from */
    uint16_t pdu_len = 0;
    unsigned timeout = 100;     /* milliseconds */
    unsigned max_apdu = 0;
    time_t elapsed_seconds = 0;
    time_t last_seconds = 0;
    time_t current_seconds = 0;
    time_t timeout_seconds = 0;
    uint8_t invoke_id = 0;
    bool found = false;
    BACNET_READ_RANGE_DATA Request;
    int iCount = 0;
    int iType = 0;
    int iKey;
    int iSecondsRun = 0;


    if (((argc != 2) && (argc != 3)) || ((argc >= 2) &&
            (strcmp(argv[1], "--help") == 0))) {
        printf("%s\n", argv[0]);
        printf("Usage: %s server local-device-instance\r\n       or\r\n"
            "       %s remote-device-instance\r\n"
            "--help gives further information\r\n",
            filename_remove_path(argv[0]), filename_remove_path(argv[0]));
        if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
            printf("\r\nServer mode:\r\n\r\n"
                "<local-device-instance> determins the device id of the application\r\n"
                "when running as the server end of a test set up. The Server simply\r\n"
                "returns dummy data for each ReadRange request\r\n\r\n"
                "Non server:\r\n\r\n"
                "<remote-device-instance> indicates the device id of the server\r\n"
                "instance of the application.\r\n"
                "The non server application will send a series of ReadRange requests to the\r\n"
                "server with examples of different range types.\r\n");
        }
        return 0;
    }
    /* decode the command line parameters */
    if (_stricmp(argv[1], "server") == 0)
        Target_Mode = 1;
    else
        Target_Mode = 0;

    Target_Device_Object_Instance = strtol(argv[1 + Target_Mode], NULL, 0);

    if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
        fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
            Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
        return 1;
    }

    /* setup my info */
    if (Target_Mode)
        Device_Set_Object_Instance_Number(Target_Device_Object_Instance);
    else
        Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);

    Init_Objects();
    address_init();
    Init_Service_Handlers();
    dlenv_init();
    atexit(datalink_cleanup);
    /* configure the timeout values */
    last_seconds = time(NULL);
    timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();

    if (Target_Mode) {
#if defined(WIN32) || defined(__BORLANDC__)
        printf("Entering server mode. press q to quit program\r\n\r\n");
#else
        printf("Entering server mode.\r\n\r\n");
#endif
        for (;;) {
            /* increment timer - exit if timed out */
            current_seconds = time(NULL);

            /* returns 0 bytes on timeout */
            pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);

            /* process */
            if (pdu_len) {
                npdu_handler(&src, &Rx_Buf[0], pdu_len);
            }
            /* at least one second has passed */
            if (current_seconds != last_seconds) {
                putchar('.');   /* Just to show that time is passing... */
                tsm_timer_milliseconds(((current_seconds -
                            last_seconds) * 1000));
                address_cache_timer(current_seconds - last_seconds);
                trend_log_timer(current_seconds - last_seconds);
                last_seconds = current_seconds;
                /* Change the analog input PVs for testing purposes */
                for (iCount = 0; iCount < Analog_Input_Count(); iCount++) {
                    Analog_Input_Present_Value_Set(iCount,
                        iSecondsRun * (iCount + 1));
                }

                iSecondsRun++;
            }
#if defined(WIN32) || defined(__BORLANDC__)
            if (_kbhit()) {
                iKey = toupper(_getch());
                if (iKey == 'Q') {
                    printf("\r\nExiting program now\r\n");
                    exit(0);
                }
            }
#endif
        }
    } else {

        /* try to bind with the device */
        found =
            address_bind_request(Target_Device_Object_Instance, &max_apdu,
            &Target_Address);
        if (!found) {
            Send_WhoIs(Target_Device_Object_Instance,
                Target_Device_Object_Instance);
        }
        /* loop forever */
        for (;;) {
            /* increment timer - exit if timed out */
            current_seconds = time(NULL);

            /* returns 0 bytes on timeout */
            pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);

            /* process */
            if (pdu_len) {
                npdu_handler(&src, &Rx_Buf[0], pdu_len);
            }
            /* at least one second has passed */
            if (current_seconds != last_seconds) {
                tsm_timer_milliseconds(((current_seconds -
                            last_seconds) * 1000));
                address_cache_timer(current_seconds - last_seconds);
                trend_log_timer(current_seconds - last_seconds);
                last_seconds = current_seconds;
            }
            if (Error_Detected)
                break;
            /* wait until the device is bound, or timeout and quit */
            if (!found)
                found =
                    address_bind_request(Target_Device_Object_Instance,
                    &max_apdu, &Target_Address);
            if (found) {
                if (invoke_id == 0) {   /* Safe to send a new request */
                    switch (iCount) {
                        case 0:        /* Pass - should read up to 1st 10 */
                            Request.RequestType = RR_BY_POSITION;
                            Request.Range.RefIndex = 1;
                            Request.Count = 10;
                            Request.object_type = OBJECT_DEVICE;
                            Request.object_instance =
                                Target_Device_Object_Instance;
                            Request.object_property =
                                PROP_DEVICE_ADDRESS_BINDING;
                            Request.array_index = 0;
                            break;

                        case 1:        /* Pass - should read entries 2 and 3 */
                            Request.RequestType = RR_BY_POSITION;
                            Request.Range.RefSeqNum = 3;
                            Request.Count = -2;
                            Request.object_type = OBJECT_DEVICE;
                            Request.object_instance =
                                Target_Device_Object_Instance;
                            Request.object_property =
                                PROP_DEVICE_ADDRESS_BINDING;
                            Request.array_index = 0;
                            break;

                        case 2:        /* Fail - By Time not supported */
                            Request.RequestType = RR_BY_TIME;
                            Request.Range.RefTime.date.year = 2009;
                            Request.Range.RefTime.date.month = 9;
                            Request.Range.RefTime.date.day = 23;
                            Request.Range.RefTime.date.wday = 0xFF;
                            Request.Range.RefTime.time.hour = 22;
                            Request.Range.RefTime.time.min = 23;
                            Request.Range.RefTime.time.sec = 24;
                            Request.Range.RefTime.time.hundredths = 0;

                            Request.Count = 10;
                            Request.object_type = OBJECT_DEVICE;
                            Request.object_instance =
                                Target_Device_Object_Instance;
                            Request.object_property =
                                PROP_DEVICE_ADDRESS_BINDING;
                            Request.array_index = 0;
                            break;

                        case 3:        /* Fail - array not supported */
                            Request.RequestType = RR_BY_POSITION;
                            Request.Range.RefIndex = 1;
                            Request.Count = 10;
                            Request.object_type = OBJECT_DEVICE;
                            Request.object_instance =
                                Target_Device_Object_Instance;
                            Request.object_property =
                                PROP_DEVICE_ADDRESS_BINDING;
                            Request.array_index = 1;
                            break;

                        case 4:        /* Fail - By Sequence not supported */
                            Request.RequestType = RR_BY_SEQUENCE;
                            Request.Range.RefSeqNum = 1;
                            Request.Count = 10;
                            Request.object_type = OBJECT_DEVICE;
                            Request.object_instance =
                                Target_Device_Object_Instance;
                            Request.object_property =
                                PROP_DEVICE_ADDRESS_BINDING;
                            Request.array_index = 0;
                            break;

                        case 5:        /* Fail Bytime not supported and array not supported */
                            Request.RequestType = RR_BY_TIME;
                            Request.Range.RefTime.date.year = 2009;
                            Request.Range.RefTime.date.month = 9;
                            Request.Range.RefTime.date.day = 23;
                            Request.Range.RefTime.date.wday = 0xFF;     /* Day of week unspecified */
                            Request.Range.RefTime.time.hour = 22;
                            Request.Range.RefTime.time.min = 23;
                            Request.Range.RefTime.time.sec = 24;
                            Request.Range.RefTime.time.hundredths = 0;

                            Request.Count = 10;
                            Request.object_type = OBJECT_DEVICE;
                            Request.object_instance =
                                Target_Device_Object_Instance;
                            Request.object_property =
                                PROP_DEVICE_ADDRESS_BINDING;
                            Request.array_index = 1;
                            break;

                        case 6:        /* Pass - should try to return all entries */
                            Request.RequestType = RR_READ_ALL;
                            Request.object_type = OBJECT_DEVICE;
                            Request.object_instance =
                                Target_Device_Object_Instance;
                            Request.object_property =
                                PROP_DEVICE_ADDRESS_BINDING;
                            Request.array_index = 0;
                            break;

                        case 7:        /* Fail - array not supported */
                            Request.RequestType = RR_READ_ALL;
                            Request.object_type = OBJECT_DEVICE;
                            Request.object_instance =
                                Target_Device_Object_Instance;
                            Request.object_property =
                                PROP_DEVICE_ADDRESS_BINDING;
                            Request.array_index = 1;
                            break;

                        case 8:        /* Pass - should read 1st 1 */
                            Request.RequestType = RR_BY_POSITION;
                            Request.Range.RefIndex = 1;
                            Request.Count = 1;
                            Request.object_type = OBJECT_DEVICE;
                            Request.object_instance =
                                Target_Device_Object_Instance;
                            Request.object_property =
                                PROP_DEVICE_ADDRESS_BINDING;
                            Request.array_index = 0;
                            break;

                        case 9:        /* Pass - should read 1st 2 */
                            Request.RequestType = RR_BY_POSITION;
                            Request.Range.RefIndex = 1;
                            Request.Count = 2;
                            Request.object_type = OBJECT_DEVICE;
                            Request.object_instance =
                                Target_Device_Object_Instance;
                            Request.object_property =
                                PROP_DEVICE_ADDRESS_BINDING;
                            Request.array_index = 0;
                            break;

                        case 10:       /* Pass - should read 2nd and 3rd */
                            Request.RequestType = RR_BY_POSITION;
                            Request.Range.RefIndex = 2;
                            Request.Count = 2;
                            Request.object_type = OBJECT_DEVICE;
                            Request.object_instance =
                                Target_Device_Object_Instance;
                            Request.object_property =
                                PROP_DEVICE_ADDRESS_BINDING;
                            Request.array_index = 0;
                            break;

                        case 11:       /* Pass - should read 2nd up to 11th */
                            Request.RequestType = RR_BY_POSITION;
                            Request.Range.RefIndex = 2;
                            Request.Count = 10;
                            Request.object_type = OBJECT_DEVICE;
                            Request.object_instance =
                                Target_Device_Object_Instance;
                            Request.object_property =
                                PROP_DEVICE_ADDRESS_BINDING;
                            Request.array_index = 0;
                            break;
                    }

                    invoke_id =
                        Send_ReadRange_Request(Target_Device_Object_Instance,
                        &Request);
                } else if (tsm_invoke_id_free(invoke_id)) {
                    if (iCount != 11) {
                        iCount++;
                        invoke_id = 0;
                    } else {
                        break;
                    }
                } else if (tsm_invoke_id_failed(invoke_id)) {
                    fprintf(stderr, "\rError: TSM Timeout!\r\n");
                    tsm_free_invoke_id(invoke_id);
                    /* Error_Detected = true; */
                    /* try again or abort? */
                    invoke_id = 0;      /* Try next operation */
                    /* break; */
                }
            } else {
                /* increment timer - exit if timed out */
                elapsed_seconds += (current_seconds - last_seconds);
                if (elapsed_seconds > timeout_seconds) {
                    printf("\rError: APDU Timeout!\r\n");
                    /* Error_Detected = true;
                       break; */
                    invoke_id = 0;
                }
            }
            /* keep track of time for next check */
            last_seconds = current_seconds;
        }
    }

    if (Error_Detected)
        return 1;
    return 0;
}
bool Notification_Class_Write_Property(
    BACNET_WRITE_PROPERTY_DATA * wp_data)
{
    NOTIFICATION_CLASS_INFO *CurrentNotify;
    NOTIFICATION_CLASS_INFO TmpNotify;
    BACNET_APPLICATION_DATA_VALUE value;
    bool status = false;
    int iOffset = 0;
    uint8_t idx = 0;
    int len = 0;



    CurrentNotify =
        &NC_Info[Notification_Class_Instance_To_Index(wp_data->
            object_instance)];

    /* decode the some of the request
     */
    len =
        bacapp_decode_application_data(wp_data->application_data,
        wp_data->application_data_len, &value);
    if (len < 0) {
        /* error while decoding - a value larger than we can handle */
        wp_data->error_class = ERROR_CLASS_PROPERTY;
        wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
        return false;
    }
    if ((wp_data->object_property != PROP_PRIORITY) &&
        (wp_data->array_index != BACNET_ARRAY_ALL)) {
        /*  only array properties can have array options */
        wp_data->error_class = ERROR_CLASS_PROPERTY;
        wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
        return false;
    }
    switch (wp_data->object_property) {
        case PROP_PRIORITY:
            status =
                WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
                &wp_data->error_class, &wp_data->error_code);

            if (status) {
                if (wp_data->array_index == 0) {
                    wp_data->error_class = ERROR_CLASS_PROPERTY;
                    wp_data->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
                } else if (wp_data->array_index == BACNET_ARRAY_ALL) {
                    /* FIXME: wite all array */
                } else if (wp_data->array_index <= 3) {
                    CurrentNotify->Priority[wp_data->array_index - 1] =
                        value.type.Unsigned_Int;
                } else {
                    wp_data->error_class = ERROR_CLASS_PROPERTY;
                    wp_data->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
                }
            }
            break;

        case PROP_ACK_REQUIRED:
            status =
                WPValidateArgType(&value, BACNET_APPLICATION_TAG_BIT_STRING,
                &wp_data->error_class, &wp_data->error_code);

            if (status) {
                if (value.type.Bit_String.bits_used == 3) {
                    CurrentNotify->Ack_Required =
                        value.type.Bit_String.value[0];
                } else {
                    wp_data->error_class = ERROR_CLASS_PROPERTY;
                    wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
                }
            }
            break;

        case PROP_RECIPIENT_LIST:

            memset(&TmpNotify, 0x00, sizeof(NOTIFICATION_CLASS_INFO));

            /* decode all packed */
            while (iOffset < wp_data->application_data_len) {
                /* Decode Valid Days */
                len =
                    bacapp_decode_application_data(&wp_data->
                    application_data[iOffset], wp_data->application_data_len,
                    &value);

                if ((len == 0) ||
                    (value.tag != BACNET_APPLICATION_TAG_BIT_STRING)) {
                    /* Bad decode, wrong tag or following required parameter missing */
                    wp_data->error_class = ERROR_CLASS_PROPERTY;
                    wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
                    return false;
                }

                if (value.type.Bit_String.bits_used == MAX_BACNET_DAYS_OF_WEEK)
                    /* store value */
                    TmpNotify.Recipient_List[idx].ValidDays =
                        value.type.Bit_String.value[0];
                else {
                    wp_data->error_class = ERROR_CLASS_PROPERTY;
                    wp_data->error_code = ERROR_CODE_OTHER;
                    return false;
                }

                iOffset += len;
                /* Decode From Time */
                len =
                    bacapp_decode_application_data(&wp_data->
                    application_data[iOffset], wp_data->application_data_len,
                    &value);

                if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_TIME)) {
                    /* Bad decode, wrong tag or following required parameter missing */
                    wp_data->error_class = ERROR_CLASS_PROPERTY;
                    wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
                    return false;
                }
                /* store value */
                TmpNotify.Recipient_List[idx].FromTime = value.type.Time;

                iOffset += len;
                /* Decode To Time */
                len =
                    bacapp_decode_application_data(&wp_data->
                    application_data[iOffset], wp_data->application_data_len,
                    &value);

                if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_TIME)) {
                    /* Bad decode, wrong tag or following required parameter missing */
                    wp_data->error_class = ERROR_CLASS_PROPERTY;
                    wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
                    return false;
                }
                /* store value */
                TmpNotify.Recipient_List[idx].ToTime = value.type.Time;

                iOffset += len;
                /* context tag [0] - Device */
                if (decode_is_context_tag(&wp_data->application_data[iOffset],
                        0)) {
                    TmpNotify.Recipient_List[idx].Recipient.RecipientType =
                        RECIPIENT_TYPE_DEVICE;
                    /* Decode Network Number */
                    len =
                        bacapp_decode_context_data(&wp_data->
                        application_data[iOffset],
                        wp_data->application_data_len, &value,
                        PROP_RECIPIENT_LIST);

                    if ((len == 0) ||
                        (value.tag != BACNET_APPLICATION_TAG_OBJECT_ID)) {
                        /* Bad decode, wrong tag or following required parameter missing */
                        wp_data->error_class = ERROR_CLASS_PROPERTY;
                        wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
                        return false;
                    }
                    /* store value */
                    TmpNotify.Recipient_List[idx].Recipient._.
                        DeviceIdentifier = value.type.Object_Id.instance;

                    iOffset += len;
                }
                /* opening tag [1] - Recipient */
                else if (decode_is_opening_tag_number(&wp_data->
                        application_data[iOffset], 1)) {
                    iOffset++;
                    TmpNotify.Recipient_List[idx].Recipient.RecipientType =
                        RECIPIENT_TYPE_ADDRESS;
                    /* Decode Network Number */
                    len =
                        bacapp_decode_application_data(&wp_data->
                        application_data[iOffset],
                        wp_data->application_data_len, &value);

                    if ((len == 0) ||
                        (value.tag != BACNET_APPLICATION_TAG_UNSIGNED_INT)) {
                        /* Bad decode, wrong tag or following required parameter missing */
                        wp_data->error_class = ERROR_CLASS_PROPERTY;
                        wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
                        return false;
                    }
                    /* store value */
                    TmpNotify.Recipient_List[idx].Recipient._.Address.net =
                        value.type.Unsigned_Int;

                    iOffset += len;
                    /* Decode Address */
                    len =
                        bacapp_decode_application_data(&wp_data->
                        application_data[iOffset],
                        wp_data->application_data_len, &value);

                    if ((len == 0) ||
                        (value.tag != BACNET_APPLICATION_TAG_OCTET_STRING)) {
                        /* Bad decode, wrong tag or following required parameter missing */
                        wp_data->error_class = ERROR_CLASS_PROPERTY;
                        wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
                        return false;
                    }
                    /* store value */
                    if (TmpNotify.Recipient_List[idx].Recipient._.Address.
                        net == 0) {
                        memcpy(TmpNotify.Recipient_List[idx].Recipient._.
                            Address.mac, value.type.Octet_String.value,
                            value.type.Octet_String.length);
                        TmpNotify.Recipient_List[idx].Recipient._.Address.
                            mac_len = value.type.Octet_String.length;
                    } else {
                        memcpy(TmpNotify.Recipient_List[idx].Recipient._.
                            Address.adr, value.type.Octet_String.value,
                            value.type.Octet_String.length);
                        TmpNotify.Recipient_List[idx].Recipient._.Address.len =
                            value.type.Octet_String.length;
                    }

                    iOffset += len;
                    /* closing tag [1] - Recipient */
                    if (decode_is_closing_tag_number(&wp_data->
                            application_data[iOffset], 1))
                        iOffset++;
                    else {
                        /* Bad decode, wrong tag or following required parameter missing */
                        wp_data->error_class = ERROR_CLASS_PROPERTY;
                        wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
                        return false;
                    }
                } else {
                    /* Bad decode, wrong tag or following required parameter missing */
                    wp_data->error_class = ERROR_CLASS_PROPERTY;
                    wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
                    return false;
                }

                /* Process Identifier */
                len =
                    bacapp_decode_application_data(&wp_data->
                    application_data[iOffset], wp_data->application_data_len,
                    &value);

                if ((len == 0) ||
                    (value.tag != BACNET_APPLICATION_TAG_UNSIGNED_INT)) {
                    /* Bad decode, wrong tag or following required parameter missing */
                    wp_data->error_class = ERROR_CLASS_PROPERTY;
                    wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
                    return false;
                }
                /* store value */
                TmpNotify.Recipient_List[idx].ProcessIdentifier =
                    value.type.Unsigned_Int;

                iOffset += len;
                /* Issue Confirmed Notifications */
                len =
                    bacapp_decode_application_data(&wp_data->
                    application_data[iOffset], wp_data->application_data_len,
                    &value);

                if ((len == 0) ||
                    (value.tag != BACNET_APPLICATION_TAG_BOOLEAN)) {
                    /* Bad decode, wrong tag or following required parameter missing */
                    wp_data->error_class = ERROR_CLASS_PROPERTY;
                    wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
                    return false;
                }
                /* store value */
                TmpNotify.Recipient_List[idx].ConfirmedNotify =
                    value.type.Boolean;

                iOffset += len;
                /* Transitions */
                len =
                    bacapp_decode_application_data(&wp_data->
                    application_data[iOffset], wp_data->application_data_len,
                    &value);

                if ((len == 0) ||
                    (value.tag != BACNET_APPLICATION_TAG_BIT_STRING)) {
                    /* Bad decode, wrong tag or following required parameter missing */
                    wp_data->error_class = ERROR_CLASS_PROPERTY;
                    wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
                    return false;
                }

                if (value.type.Bit_String.bits_used ==
                    MAX_BACNET_EVENT_TRANSITION)
                    /* store value */
                    TmpNotify.Recipient_List[idx].Transitions =
                        value.type.Bit_String.value[0];
                else {
                    wp_data->error_class = ERROR_CLASS_PROPERTY;
                    wp_data->error_code = ERROR_CODE_OTHER;
                    return false;
                }
                iOffset += len;

                /* Increasing element of list */
                if (++idx >= NC_MAX_RECIPIENTS) {
                    wp_data->error_class = ERROR_CLASS_RESOURCES;
                    wp_data->error_code =
                        ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
                    return false;
                }
            }

            /* Decoded all recipient list */
            /* copy elements from temporary object */
            for (idx = 0; idx < NC_MAX_RECIPIENTS; idx++) {
                BACNET_ADDRESS src = { 0 };
                unsigned max_apdu = 0;
                int32_t DeviceID;

                CurrentNotify->Recipient_List[idx] =
                    TmpNotify.Recipient_List[idx];

                if (CurrentNotify->Recipient_List[idx].Recipient.
                    RecipientType == RECIPIENT_TYPE_DEVICE) {
                    /* copy Device_ID */
                    DeviceID =
                        CurrentNotify->Recipient_List[idx].Recipient._.
                        DeviceIdentifier;
                    address_bind_request(DeviceID, &max_apdu, &src);

                } else if (CurrentNotify->Recipient_List[idx].Recipient.
                    RecipientType == RECIPIENT_TYPE_ADDRESS) {
                    /* copy Address */
                    /* src = CurrentNotify->Recipient_List[idx].Recipient._.Address; */
                    /* address_bind_request(BACNET_MAX_INSTANCE, &max_apdu, &src); */
                }
            }

            status = true;

            break;

        default:
            wp_data->error_class = ERROR_CLASS_PROPERTY;
            wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
            break;
    }

    return status;
}