Added some missing services to APDU. Fix maxes. Refactor Simple Ack.

This commit is contained in:
Steve Karg
2022-11-06 10:34:44 -06:00
parent 64d1461549
commit a3fd5b9fc3
3 changed files with 135 additions and 161 deletions
+2 -1
View File
@@ -1478,7 +1478,7 @@ typedef enum BACnet_Confirmed_Service_Choice {
/* Services added after 2016 */
/* confirmed-audit-notification [32] see Alarm and Event Services */
/* audit-log-query [33] see Object Access Services */
MAX_BACNET_CONFIRMED_SERVICE = 30
MAX_BACNET_CONFIRMED_SERVICE = 34
} BACNET_CONFIRMED_SERVICE;
/* BACnetUnconfirmedServiceChoice ::= ENUMERATED */
@@ -1515,6 +1515,7 @@ typedef enum BACnet_Services_Supported {
/* Alarm and Event Services */
SERVICE_SUPPORTED_ACKNOWLEDGE_ALARM = 0,
SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION = 1,
SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION_MULTIPLE = 42,
SERVICE_SUPPORTED_CONFIRMED_EVENT_NOTIFICATION = 2,
SERVICE_SUPPORTED_GET_ALARM_SUMMARY = 3,
SERVICE_SUPPORTED_GET_ENROLLMENT_SUMMARY = 4,
+129 -160
View File
@@ -76,7 +76,11 @@ static BACNET_SERVICES_SUPPORTED
SERVICE_SUPPORTED_AUTHENTICATE, SERVICE_SUPPORTED_REQUEST_KEY,
SERVICE_SUPPORTED_READ_RANGE, SERVICE_SUPPORTED_LIFE_SAFETY_OPERATION,
SERVICE_SUPPORTED_SUBSCRIBE_COV_PROPERTY,
SERVICE_SUPPORTED_GET_EVENT_INFORMATION
SERVICE_SUPPORTED_GET_EVENT_INFORMATION,
SERVICE_SUPPORTED_SUBSCRIBE_COV_PROPERTY_MULTIPLE,
SERVICE_SUPPORTED_CONFIRMED_COV_NOTIFICATION_MULTIPLE,
SERVICE_SUPPORTED_CONFIRMED_AUDIT_NOTIFICATION,
SERVICE_SUPPORTED_AUDIT_LOG_QUERY
};
/* a simple table for crossing the services supported */
@@ -88,7 +92,13 @@ static BACNET_SERVICES_SUPPORTED
SERVICE_SUPPORTED_UNCONFIRMED_PRIVATE_TRANSFER,
SERVICE_SUPPORTED_UNCONFIRMED_TEXT_MESSAGE,
SERVICE_SUPPORTED_TIME_SYNCHRONIZATION, SERVICE_SUPPORTED_WHO_HAS,
SERVICE_SUPPORTED_WHO_IS, SERVICE_SUPPORTED_UTC_TIME_SYNCHRONIZATION
SERVICE_SUPPORTED_WHO_IS,
SERVICE_SUPPORTED_UTC_TIME_SYNCHRONIZATION,
SERVICE_SUPPORTED_WRITE_GROUP,
SERVICE_SUPPORTED_UNCONFIRMED_COV_NOTIFICATION_MULTIPLE,
SERVICE_SUPPORTED_UNCONFIRMED_AUDIT_NOTIFICATION,
SERVICE_SUPPORTED_WHO_AM_I,
SERVICE_SUPPORTED_YOU_ARE
};
/* Confirmed Function Handlers */
@@ -241,16 +251,24 @@ static union {
confirmed_ack_function complex;
} Confirmed_ACK_Function[MAX_BACNET_CONFIRMED_SERVICE];
void apdu_set_confirmed_simple_ack_handler(
BACNET_CONFIRMED_SERVICE service_choice,
confirmed_simple_ack_function pFunction)
/**
* @brief Determine if the BACnet service is a Simple Ack Service
* @param service_choice [in] BACnet confirmed service choice
*/
bool apdu_confirmed_simple_ack_service(
BACNET_CONFIRMED_SERVICE service_choice)
{
bool status = false;
switch (service_choice) {
case SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM:
case SERVICE_CONFIRMED_AUDIT_NOTIFICATION:
case SERVICE_CONFIRMED_COV_NOTIFICATION:
case SERVICE_CONFIRMED_COV_NOTIFICATION_MULTIPLE:
case SERVICE_CONFIRMED_EVENT_NOTIFICATION:
case SERVICE_CONFIRMED_SUBSCRIBE_COV:
case SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY:
case SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY_MULTIPLE:
case SERVICE_CONFIRMED_LIFE_SAFETY_OPERATION:
/* Object Access Services */
case SERVICE_CONFIRMED_ADD_LIST_ELEMENT:
@@ -266,40 +284,29 @@ void apdu_set_confirmed_simple_ack_handler(
case SERVICE_CONFIRMED_VT_CLOSE:
/* Security Services */
case SERVICE_CONFIRMED_REQUEST_KEY:
Confirmed_ACK_Function[service_choice].simple = pFunction;
status = true;
break;
default:
break;
}
return status;
}
void apdu_set_confirmed_simple_ack_handler(
BACNET_CONFIRMED_SERVICE service_choice,
confirmed_simple_ack_function pFunction)
{
if (apdu_confirmed_simple_ack_service(service_choice)) {
Confirmed_ACK_Function[service_choice].simple = pFunction;
}
}
void apdu_set_confirmed_ack_handler(
BACNET_CONFIRMED_SERVICE service_choice, confirmed_ack_function pFunction)
{
switch (service_choice) {
case SERVICE_CONFIRMED_GET_ALARM_SUMMARY:
case SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY:
case SERVICE_CONFIRMED_GET_EVENT_INFORMATION:
/* File Access Services */
case SERVICE_CONFIRMED_ATOMIC_READ_FILE:
case SERVICE_CONFIRMED_ATOMIC_WRITE_FILE:
/* Object Access Services */
case SERVICE_CONFIRMED_CREATE_OBJECT:
case SERVICE_CONFIRMED_READ_PROPERTY:
case SERVICE_CONFIRMED_READ_PROP_CONDITIONAL:
case SERVICE_CONFIRMED_READ_PROP_MULTIPLE:
case SERVICE_CONFIRMED_READ_RANGE:
/* Remote Device Management Services */
case SERVICE_CONFIRMED_PRIVATE_TRANSFER:
/* Virtual Terminal Services */
case SERVICE_CONFIRMED_VT_OPEN:
case SERVICE_CONFIRMED_VT_DATA:
/* Security Services */
case SERVICE_CONFIRMED_AUTHENTICATE:
Confirmed_ACK_Function[service_choice].complex = pFunction;
break;
default:
break;
if (!apdu_confirmed_simple_ack_service(service_choice)) {
Confirmed_ACK_Function[service_choice].complex = pFunction;
}
}
@@ -578,109 +585,68 @@ void apdu_handler(BACNET_ADDRESS *src,
}
break;
case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
if (apdu_len >= 2) {
service_choice = apdu[1];
service_request = &apdu[2];
service_request_len = apdu_len - 2;
if (apdu_unconfirmed_dcc_disabled(service_choice)) {
/* When network communications are disabled,
only DeviceCommunicationControl and
ReinitializeDevice APDUs shall be processed and no
messages shall be initiated. If communications have
been initiation disabled, then WhoIs may be
processed. */
break;
}
if (service_choice < MAX_BACNET_UNCONFIRMED_SERVICE) {
if (Unconfirmed_Function[service_choice]) {
Unconfirmed_Function[service_choice](
service_request, service_request_len, src);
}
if (apdu_len < 3) {
break;
}
service_choice = apdu[1];
service_request = &apdu[2];
service_request_len = apdu_len - 2;
if (apdu_unconfirmed_dcc_disabled(service_choice)) {
/* When network communications are disabled,
only DeviceCommunicationControl and
ReinitializeDevice APDUs shall be processed and no
messages shall be initiated. If communications have
been initiation disabled, then WhoIs may be
processed. */
break;
}
if (service_choice < MAX_BACNET_UNCONFIRMED_SERVICE) {
if (Unconfirmed_Function[service_choice]) {
Unconfirmed_Function[service_choice](
service_request, service_request_len, src);
}
}
break;
case PDU_TYPE_SIMPLE_ACK:
if (apdu_len >= 3) {
invoke_id = apdu[1];
service_choice = apdu[2];
switch (service_choice) {
case SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM:
case SERVICE_CONFIRMED_COV_NOTIFICATION:
case SERVICE_CONFIRMED_EVENT_NOTIFICATION:
case SERVICE_CONFIRMED_SUBSCRIBE_COV:
case SERVICE_CONFIRMED_SUBSCRIBE_COV_PROPERTY:
case SERVICE_CONFIRMED_LIFE_SAFETY_OPERATION:
/* Object Access Services */
case SERVICE_CONFIRMED_ADD_LIST_ELEMENT:
case SERVICE_CONFIRMED_REMOVE_LIST_ELEMENT:
case SERVICE_CONFIRMED_DELETE_OBJECT:
case SERVICE_CONFIRMED_WRITE_PROPERTY:
case SERVICE_CONFIRMED_WRITE_PROP_MULTIPLE:
/* Remote Device Management Services */
case SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL:
case SERVICE_CONFIRMED_REINITIALIZE_DEVICE:
case SERVICE_CONFIRMED_TEXT_MESSAGE:
/* Virtual Terminal Services */
case SERVICE_CONFIRMED_VT_CLOSE:
/* Security Services */
case SERVICE_CONFIRMED_REQUEST_KEY:
if (Confirmed_ACK_Function[service_choice].simple !=
NULL) {
Confirmed_ACK_Function[service_choice].simple(
src, invoke_id);
}
tsm_free_invoke_id(invoke_id);
break;
default:
break;
if (apdu_len < 3) {
break;
}
invoke_id = apdu[1];
service_choice = apdu[2];
if (apdu_confirmed_simple_ack_service(service_choice)) {
if (Confirmed_ACK_Function[service_choice].simple !=
NULL) {
Confirmed_ACK_Function[service_choice].simple(
src, invoke_id);
}
tsm_free_invoke_id(invoke_id);
}
break;
case PDU_TYPE_COMPLEX_ACK:
if (apdu_len >= 3) {
service_ack_data.segmented_message =
(apdu[0] & BIT(3)) ? true : false;
service_ack_data.more_follows =
(apdu[0] & BIT(2)) ? true : false;
invoke_id = service_ack_data.invoke_id = apdu[1];
len = 2;
if (service_ack_data.segmented_message) {
service_ack_data.sequence_number = apdu[len++];
service_ack_data.proposed_window_number = apdu[len++];
}
service_choice = apdu[len++];
service_request = &apdu[len];
service_request_len = apdu_len - (uint16_t)len;
switch (service_choice) {
case SERVICE_CONFIRMED_GET_ALARM_SUMMARY:
case SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY:
case SERVICE_CONFIRMED_GET_EVENT_INFORMATION:
/* File Access Services */
case SERVICE_CONFIRMED_ATOMIC_READ_FILE:
case SERVICE_CONFIRMED_ATOMIC_WRITE_FILE:
/* Object Access Services */
case SERVICE_CONFIRMED_CREATE_OBJECT:
case SERVICE_CONFIRMED_READ_PROPERTY:
case SERVICE_CONFIRMED_READ_PROP_CONDITIONAL:
case SERVICE_CONFIRMED_READ_PROP_MULTIPLE:
case SERVICE_CONFIRMED_READ_RANGE:
case SERVICE_CONFIRMED_PRIVATE_TRANSFER:
/* Virtual Terminal Services */
case SERVICE_CONFIRMED_VT_OPEN:
case SERVICE_CONFIRMED_VT_DATA:
/* Security Services */
case SERVICE_CONFIRMED_AUTHENTICATE:
if (Confirmed_ACK_Function[service_choice]
.complex != NULL) {
Confirmed_ACK_Function[service_choice].complex(
service_request, service_request_len, src,
&service_ack_data);
}
tsm_free_invoke_id(invoke_id);
break;
default:
break;
if (apdu_len < 3) {
break;
}
service_ack_data.segmented_message =
(apdu[0] & BIT(3)) ? true : false;
service_ack_data.more_follows =
(apdu[0] & BIT(2)) ? true : false;
invoke_id = service_ack_data.invoke_id = apdu[1];
len = 2;
if (service_ack_data.segmented_message) {
service_ack_data.sequence_number = apdu[len++];
service_ack_data.proposed_window_number = apdu[len++];
}
service_choice = apdu[len++];
service_request = &apdu[len];
service_request_len = apdu_len - (uint16_t)len;
if (!apdu_confirmed_simple_ack_service(service_choice)) {
if (Confirmed_ACK_Function[service_choice]
.complex != NULL) {
Confirmed_ACK_Function[service_choice].complex(
service_request, service_request_len, src,
&service_ack_data);
}
tsm_free_invoke_id(invoke_id);
}
break;
case PDU_TYPE_SEGMENT_ACK:
@@ -688,49 +654,52 @@ void apdu_handler(BACNET_ADDRESS *src,
we could check src to see if that matched the tsm */
tsm_free_invoke_id(invoke_id);
break;
case PDU_TYPE_ERROR:
if (apdu_len >= 3) {
invoke_id = apdu[1];
service_choice = apdu[2];
if (apdu_complex_error(service_choice)) {
if (Error_Function[service_choice].complex) {
Error_Function[service_choice].complex(src,
invoke_id, service_choice, &apdu[3],
apdu_len - 3);
}
} else if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) {
len = bacerror_decode_error_class_and_code(
&apdu[3], apdu_len - 3, &error_class, &error_code);
if ((len != 0) &&
(Error_Function[service_choice].error)) {
Error_Function[service_choice].error(src, invoke_id,
(BACNET_ERROR_CLASS)error_class,
(BACNET_ERROR_CODE)error_code);
}
}
tsm_free_invoke_id(invoke_id);
case PDU_TYPE_ERROR:
if (apdu_len < 3) {
break;
}
invoke_id = apdu[1];
service_choice = apdu[2];
if (apdu_complex_error(service_choice)) {
if (Error_Function[service_choice].complex) {
Error_Function[service_choice].complex(src,
invoke_id, service_choice, &apdu[3],
apdu_len - 3);
}
} else if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) {
len = bacerror_decode_error_class_and_code(
&apdu[3], apdu_len - 3, &error_class, &error_code);
if ((len != 0) &&
(Error_Function[service_choice].error)) {
Error_Function[service_choice].error(src, invoke_id,
(BACNET_ERROR_CLASS)error_class,
(BACNET_ERROR_CODE)error_code);
}
}
tsm_free_invoke_id(invoke_id);
break;
case PDU_TYPE_REJECT:
if (apdu_len >= 3) {
invoke_id = apdu[1];
reason = apdu[2];
if (Reject_Function) {
Reject_Function(src, invoke_id, reason);
}
tsm_free_invoke_id(invoke_id);
if (apdu_len < 3) {
break;
}
invoke_id = apdu[1];
reason = apdu[2];
if (Reject_Function) {
Reject_Function(src, invoke_id, reason);
}
tsm_free_invoke_id(invoke_id);
break;
case PDU_TYPE_ABORT:
if (apdu_len >= 3) {
server = apdu[0] & 0x01;
invoke_id = apdu[1];
reason = apdu[2];
if (Abort_Function) {
Abort_Function(src, invoke_id, reason, server);
}
tsm_free_invoke_id(invoke_id);
if (apdu_len < 3) {
break;
}
server = apdu[0] & 0x01;
invoke_id = apdu[1];
reason = apdu[2];
if (Abort_Function) {
Abort_Function(src, invoke_id, reason, server);
}
tsm_free_invoke_id(invoke_id);
break;
default:
break;
+4
View File
@@ -125,6 +125,10 @@ extern "C" {
BACNET_CONFIRMED_SERVICE service_choice,
confirmed_ack_function pFunction);
BACNET_STACK_EXPORT
bool apdu_confirmed_simple_ack_service(
BACNET_CONFIRMED_SERVICE service_choice);
BACNET_STACK_EXPORT
void apdu_set_confirmed_simple_ack_handler(
BACNET_CONFIRMED_SERVICE service_choice,