diff --git a/ports/arduino_uno/bvlc-arduino.c b/ports/arduino_uno/bvlc-arduino.c index e7e8c60f..2f8fd8bd 100644 --- a/ports/arduino_uno/bvlc-arduino.c +++ b/ports/arduino_uno/bvlc-arduino.c @@ -19,6 +19,13 @@ BACNET_BVLC_RESULT BVLC_Result_Code = BVLC_RESULT_SUCCESSFUL_COMPLETION; /** The current BVLC Function Code being handled. */ BACNET_BVLC_FUNCTION BVLC_Function_Code = BVLC_RESULT; /* A safe default */ +/** Encode the BVLC Result message + * + * @param pdu - buffer to store the encoding + * @param result_code - BVLC result code + * + * @return number of bytes encoded + */ static int bvlc_encode_bvlc_result(uint8_t * pdu, BACNET_BVLC_RESULT result_code) { @@ -35,6 +42,19 @@ static int bvlc_encode_bvlc_result(uint8_t * pdu, return 6; } +/** + * The common send function for bvlc functions, using b/ip. + * + * @param dest_addr - Points to a sockaddr_in structure containing the + * destination address. The length and format of the address depend + * on the address family of the socket (AF_INET). + * The address is in network byte order. + * @param dest_port - Destination port number + * @param mtu - the bytes of data to send + * @param mtu_len - the number of bytes of data to send + * @return Upon successful completion, returns the number of bytes sent. + * Otherwise, -1 shall be returned and errno set to indicate the error. + */ static int bvlc_send_mpdu(uint8_t * dest_addr, /* the destination address */ uint16_t * dest_port, /* the destination port */ @@ -51,6 +71,11 @@ static int bvlc_send_mpdu(uint8_t * dest_addr, /* the destination address */ return sendto_func(bip_socket(), mtu, mtu_len, dest_addr, *dest_port); } +/** Sends a BVLC Result + * + * @param dest_addr - destination address + * @param dest_port - destination port + */ static void bvlc_send_result(uint8_t * dest_addr, uint16_t * dest_port, /* the destination address */ @@ -65,50 +90,65 @@ static void bvlc_send_result(uint8_t * dest_addr, return; } +/** Note any BVLC_RESULT code, or NAK the BVLL message in the unsupported cases. + * Use this handler when you are not a BBMD. + * Sets the BVLC_Function_Code in case it is needed later. + * + * @param addr [in] Socket address to send any NAK back to. + * @param port [in] Socket port + * @param npdu [in] The received buffer. + * @param received_bytes [in] How many bytes in npdu[]. + * @return Non-zero BVLC_RESULT_ code if we sent a response (NAK) to this + * BVLC message. If zero, may need further processing. + */ uint16_t bvlc_for_non_bbmd(uint8_t * addr, uint16_t * port, uint8_t * npdu, uint16_t received_bytes) { - uint16_t result_code = 0; /* aka, BVLC_RESULT_SUCCESSFUL_COMPLETION */ - BVLC_Function_Code = npdu[1]; /* The BVLC function */ - switch (BVLC_Function_Code) { - case BVLC_RESULT: - if (received_bytes >= 6) { - /* This is the result of our foreign device registration */ - (void) decode_unsigned16(&npdu[4], &result_code); - BVLC_Result_Code = (BACNET_BVLC_RESULT) result_code; - fprintf(stderr, "BVLC: Result Code=%d\n", BVLC_Result_Code); - /* But don't send any response */ - result_code = 0; - } - break; - case BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE: - result_code = BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK; - break; - case BVLC_READ_BROADCAST_DIST_TABLE: - result_code = BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK; - break; - /* case BVLC_READ_BROADCAST_DIST_TABLE_ACK: */ - case BVLC_REGISTER_FOREIGN_DEVICE: - result_code = BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK; - break; - case BVLC_READ_FOREIGN_DEVICE_TABLE: - result_code = BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK; - break; - /* case BVLC_READ_FOREIGN_DEVICE_TABLE_ACK: */ - case BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY: - result_code = BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK; - break; - case BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK: - result_code = BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK; - break; - /* case BVLC_FORWARDED_NPDU: */ - /* case BVLC_ORIGINAL_UNICAST_NPDU: */ - /* case BVLC_ORIGINAL_BROADCAST_NPDU: */ - default: - break; + + /* To check the BVLC-function code, the buffer of received + * bytes has to be at least one byte long. */ + if (received_bytes >= 1) { + BVLC_Function_Code = npdu[1]; /* The BVLC function */ + switch (BVLC_Function_Code) { + case BVLC_RESULT: + if (received_bytes >= 6) { + /* This is the result of our foreign device registration */ + (void) decode_unsigned16(&npdu[4], &result_code); + BVLC_Result_Code = (BACNET_BVLC_RESULT) result_code; + fprintf(stderr, "BVLC: Result Code=%d\n", BVLC_Result_Code); + /* But don't send any response */ + result_code = 0; + } + break; + case BVLC_WRITE_BROADCAST_DISTRIBUTION_TABLE: + result_code = BVLC_RESULT_WRITE_BROADCAST_DISTRIBUTION_TABLE_NAK; + break; + case BVLC_READ_BROADCAST_DIST_TABLE: + result_code = BVLC_RESULT_READ_BROADCAST_DISTRIBUTION_TABLE_NAK; + break; + /* case BVLC_READ_BROADCAST_DIST_TABLE_ACK: */ + case BVLC_REGISTER_FOREIGN_DEVICE: + result_code = BVLC_RESULT_REGISTER_FOREIGN_DEVICE_NAK; + break; + case BVLC_READ_FOREIGN_DEVICE_TABLE: + result_code = BVLC_RESULT_READ_FOREIGN_DEVICE_TABLE_NAK; + break; + /* case BVLC_READ_FOREIGN_DEVICE_TABLE_ACK: */ + case BVLC_DELETE_FOREIGN_DEVICE_TABLE_ENTRY: + result_code = BVLC_RESULT_DELETE_FOREIGN_DEVICE_TABLE_ENTRY_NAK; + break; + case BVLC_DISTRIBUTE_BROADCAST_TO_NETWORK: + result_code = BVLC_RESULT_DISTRIBUTE_BROADCAST_TO_NETWORK_NAK; + break; + /* case BVLC_FORWARDED_NPDU: */ + /* case BVLC_ORIGINAL_UNICAST_NPDU: */ + /* case BVLC_ORIGINAL_BROADCAST_NPDU: */ + default: + break; + } } if (result_code > 0) { @@ -118,6 +158,13 @@ uint16_t bvlc_for_non_bbmd(uint8_t * addr, return result_code; } +/** Returns the current BVLL Function Code we are processing. + * We have to store this higher layer code for when the lower layers + * need to know what it is, especially to differentiate between + * BVLC_ORIGINAL_UNICAST_NPDU and BVLC_ORIGINAL_BROADCAST_NPDU. + * + * @return A BVLC_ function code, such as BVLC_ORIGINAL_UNICAST_NPDU. + */ BACNET_BVLC_FUNCTION bvlc_get_function_code(void) { return BVLC_Function_Code; diff --git a/src/bacnet/basic/object/schedule.c b/src/bacnet/basic/object/schedule.c index c30cb7a8..cba7e166 100644 --- a/src/bacnet/basic/object/schedule.c +++ b/src/bacnet/basic/object/schedule.c @@ -70,28 +70,31 @@ void Schedule_Property_Lists( void Schedule_Init(void) { unsigned i, j; - for (i = 0; i < MAX_SCHEDULES; i++) { + + SCHEDULE_DESCR *psched = &Schedule_Descr[0]; + + for (i = 0; i < MAX_SCHEDULES; i++, psched++) { /* whole year, change as neccessary */ - Schedule_Descr[i].Start_Date.year = 0xFF; - Schedule_Descr[i].Start_Date.month = 1; - Schedule_Descr[i].Start_Date.day = 1; - Schedule_Descr[i].Start_Date.wday = 0xFF; - Schedule_Descr[i].End_Date.year = 0xFF; - Schedule_Descr[i].End_Date.month = 12; - Schedule_Descr[i].End_Date.day = 31; - Schedule_Descr[i].End_Date.wday = 0xFF; + psched->Start_Date.year = 0xFF; + psched->Start_Date.month = 1; + psched->Start_Date.day = 1; + psched->Start_Date.wday = 0xFF; + psched->End_Date.year = 0xFF; + psched->End_Date.month = 12; + psched->End_Date.day = 31; + psched->End_Date.wday = 0xFF; for (j = 0; j < 7; j++) { - Schedule_Descr[i].Weekly_Schedule[j].TV_Count = 0; + psched->Weekly_Schedule[j].TV_Count = 0; } - Schedule_Descr[i].Present_Value = &Schedule_Descr[i].Schedule_Default; - Schedule_Descr[i].Schedule_Default.context_specific = false; - Schedule_Descr[i].Schedule_Default.tag = BACNET_APPLICATION_TAG_REAL; - Schedule_Descr[i].Schedule_Default.type.Real = + psched->Present_Value = &psched->Schedule_Default; + psched->Schedule_Default.context_specific = false; + psched->Schedule_Default.tag = BACNET_APPLICATION_TAG_REAL; + psched->Schedule_Default.type.Real = 21.0; /* 21 C, room temperature */ - Schedule_Descr[i].obj_prop_ref_cnt = + psched->obj_prop_ref_cnt = 0; /* no references, add as needed */ - Schedule_Descr[i].Priority_For_Writing = 16; /* lowest priority */ - Schedule_Descr[i].Out_Of_Service = false; + psched->Priority_For_Writing = 16; /* lowest priority */ + psched->Out_Of_Service = false; } } diff --git a/src/bacnet/basic/tsm/tsm.c b/src/bacnet/basic/tsm/tsm.c index e42dc7b3..227692c6 100644 --- a/src/bacnet/basic/tsm/tsm.c +++ b/src/bacnet/basic/tsm/tsm.c @@ -199,22 +199,24 @@ void tsm_set_confirmed_unsegmented_transaction(uint8_t invokeID, { uint16_t j = 0; uint8_t index; + BACNET_TSM_DATA *plist; if (invokeID) { index = tsm_find_invokeID_index(invokeID); if (index < MAX_TSM_TRANSACTIONS) { + plist = &TSM_List[index]; /* SendConfirmedUnsegmented */ - TSM_List[index].state = TSM_STATE_AWAIT_CONFIRMATION; - TSM_List[index].RetryCount = 0; + plist->state = TSM_STATE_AWAIT_CONFIRMATION; + plist->RetryCount = 0; /* start the timer */ - TSM_List[index].RequestTimer = apdu_timeout(); + plist->RequestTimer = apdu_timeout(); /* copy the data */ for (j = 0; j < apdu_len; j++) { - TSM_List[index].apdu[j] = apdu[j]; + plist->apdu[j] = apdu[j]; } - TSM_List[index].apdu_len = apdu_len; - npdu_copy_data(&TSM_List[index].npdu_data, ndpu_data); - bacnet_address_copy(&TSM_List[index].dest, dest); + plist->apdu_len = apdu_len; + npdu_copy_data(&plist->npdu_data, ndpu_data); + bacnet_address_copy(&plist->dest, dest); } } @@ -232,6 +234,7 @@ bool tsm_get_transaction_pdu(uint8_t invokeID, uint16_t j = 0; uint8_t index; bool found = false; + BACNET_TSM_DATA *plist; if (invokeID) { index = tsm_find_invokeID_index(invokeID); @@ -240,13 +243,16 @@ bool tsm_get_transaction_pdu(uint8_t invokeID, /* FIXME: we may want to free the transaction so it doesn't timeout */ /* retrieve the transaction */ - /* FIXME: bounds check the pdu_len? */ - *apdu_len = (uint16_t)TSM_List[index].apdu_len; - for (j = 0; j < *apdu_len; j++) { - apdu[j] = TSM_List[index].apdu[j]; + plist = &TSM_List[index]; + *apdu_len = (uint16_t)plist->apdu_len; + if (*apdu_len > MAX_PDU) { + *apdu_len = MAX_PDU; } - npdu_copy_data(ndpu_data, &TSM_List[index].npdu_data); - bacnet_address_copy(dest, &TSM_List[index].dest); + for (j = 0; j < *apdu_len; j++) { + apdu[j] = plist->apdu[j]; + } + npdu_copy_data(ndpu_data, &plist->npdu_data); + bacnet_address_copy(dest, &plist->dest); found = true; } } @@ -254,33 +260,38 @@ bool tsm_get_transaction_pdu(uint8_t invokeID, return found; } -/* called once a millisecond or slower */ +/** Called once a millisecond or slower. + * + * @param milliseconds - Count of milliseconds passed, since the last call. + */ void tsm_timer_milliseconds(uint16_t milliseconds) { unsigned i = 0; /* counter */ - for (i = 0; i < MAX_TSM_TRANSACTIONS; i++) { - if (TSM_List[i].state == TSM_STATE_AWAIT_CONFIRMATION) { - if (TSM_List[i].RequestTimer > milliseconds) { - TSM_List[i].RequestTimer -= milliseconds; + BACNET_TSM_DATA *plist = &TSM_List[0]; + + for (i = 0; i < MAX_TSM_TRANSACTIONS; i++, plist++) { + if (plist->state == TSM_STATE_AWAIT_CONFIRMATION) { + if (plist->RequestTimer > milliseconds) { + plist->RequestTimer -= milliseconds; } else { - TSM_List[i].RequestTimer = 0; + plist->RequestTimer = 0; } /* AWAIT_CONFIRMATION */ - if (TSM_List[i].RequestTimer == 0) { - if (TSM_List[i].RetryCount < apdu_retries()) { - TSM_List[i].RequestTimer = apdu_timeout(); - TSM_List[i].RetryCount++; - datalink_send_pdu(&TSM_List[i].dest, &TSM_List[i].npdu_data, - &TSM_List[i].apdu[0], TSM_List[i].apdu_len); + if (plist->RequestTimer == 0) { + if (plist->RetryCount < apdu_retries()) { + plist->RequestTimer = apdu_timeout(); + plist->RetryCount++; + datalink_send_pdu(&plist->dest, &plist->npdu_data, + &plist->apdu[0], plist->apdu_len); } else { /* note: the invoke id has not been cleared yet and this indicates a failed message: IDLE and a valid invoke id */ - TSM_List[i].state = TSM_STATE_IDLE; - if (TSM_List[i].InvokeID != 0) { + plist->state = TSM_STATE_IDLE; + if (plist->InvokeID != 0) { if (Timeout_Function) { - Timeout_Function(TSM_List[i].InvokeID); + Timeout_Function(plist->InvokeID); } } } @@ -293,11 +304,13 @@ void tsm_timer_milliseconds(uint16_t milliseconds) void tsm_free_invoke_id(uint8_t invokeID) { uint8_t index; + BACNET_TSM_DATA *plist; index = tsm_find_invokeID_index(invokeID); if (index < MAX_TSM_TRANSACTIONS) { - TSM_List[index].state = TSM_STATE_IDLE; - TSM_List[index].InvokeID = 0; + plist = &TSM_List[index]; + plist->state = TSM_STATE_IDLE; + plist->InvokeID = 0; } }