Feature/refactor-apps-string-parsing (#1152)
* Added bacnet_str functions for parsing various numeric strings. * Renamed BACnet string API to be clearer when no stdlib function exists. * Fixed incompatible types - from 'BACNET_UNSIGNED_INTEGER *' to 'unsigned long *' warning * Changed bacnet-str-to functions to use ERANGE for error detection. * Refactored some apps to use common string parsing for BACnet data types. * Refactor bacapp_parse_application_data to use bacnet_string_to_unsigned for better clarity * Added strtol for BACnetEventType.
This commit is contained in:
@@ -2827,6 +2827,179 @@ const char *bactext_timer_transition_name(uint32_t index)
|
||||
bactext_timer_transition_names, index, ASHRAE_Reserved_String);
|
||||
}
|
||||
|
||||
INDTEXT_DATA bactext_boolean_value_names[] = { { false, "false" },
|
||||
{ true, "true" },
|
||||
{ 0, NULL } };
|
||||
|
||||
const char *bactext_boolean_value_name(uint32_t index)
|
||||
{
|
||||
return indtext_by_index_default(
|
||||
bactext_boolean_value_names, index, ASHRAE_Reserved_String);
|
||||
}
|
||||
|
||||
bool bactext_property_states_strtoul(
|
||||
BACNET_PROPERTY_STATES property_state,
|
||||
const char *search_name,
|
||||
uint32_t *found_index)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
switch (property_state) {
|
||||
case PROP_STATE_BOOLEAN_VALUE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_boolean_value_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_BINARY_VALUE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_binary_present_value_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_EVENT_TYPE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_event_type_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_POLARITY:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_binary_polarity_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_PROGRAM_CHANGE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_program_request_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_PROGRAM_STATE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_program_state_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_REASON_FOR_HALT:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_program_error_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_RELIABILITY:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_reliability_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_EVENT_STATE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_event_state_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_SYSTEM_STATUS:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_device_status_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_UNITS:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_engineering_unit_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_LIFE_SAFETY_MODE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_life_safety_mode_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_LIFE_SAFETY_STATE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_life_safety_state_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_RESTART_REASON:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_restart_reason_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_LIFE_SAFETY_OPERATION:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_life_safety_operation_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_NODE_TYPE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_node_type_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_NOTIFY_TYPE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_notify_type_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_SHED_STATE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_shed_state_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_SILENCED_STATE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_silenced_state_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_LIGHTING_IN_PROGRESS:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_lighting_in_progress_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_LIGHTING_OPERATION:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_lighting_operation_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_LIGHTING_TRANSITION:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_lighting_transition_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_BINARY_LIGHTING_VALUE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bacnet_binary_lighting_pv_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_TIMER_STATE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_timer_state_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_TIMER_TRANSITION:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_timer_transition_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_NETWORK_PORT_COMMAND:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_network_port_command_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_NETWORK_TYPE:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_network_port_type_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_NETWORK_NUMBER_QUALITY:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_network_number_quality_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_PROTOCOL_LEVEL:
|
||||
status = bactext_string_to_uint32_index(
|
||||
bactext_protocol_level_names, search_name, found_index);
|
||||
break;
|
||||
case PROP_STATE_ACTION:
|
||||
case PROP_STATE_DOOR_SECURED_STATUS:
|
||||
case PROP_STATE_DOOR_STATUS:
|
||||
case PROP_STATE_DOOR_VALUE:
|
||||
case PROP_STATE_FILE_ACCESS_METHOD:
|
||||
case PROP_STATE_LOCK_STATUS:
|
||||
case PROP_STATE_MAINTENANCE:
|
||||
case PROP_STATE_SECURITY_LEVEL:
|
||||
case PROP_STATE_ACCESS_EVENT:
|
||||
case PROP_STATE_ZONE_OCCUPANCY_STATE:
|
||||
case PROP_STATE_ACCESS_CRED_DISABLE_REASON:
|
||||
case PROP_STATE_ACCESS_CRED_DISABLE:
|
||||
case PROP_STATE_AUTHENTICATION_STATUS:
|
||||
case PROP_STATE_BACKUP_STATE:
|
||||
case PROP_STATE_WRITE_STATUS:
|
||||
case PROP_STATE_INTEGER_VALUE:
|
||||
case PROP_STATE_BACNET_IP_MODE:
|
||||
case PROP_STATE_ESCALATOR_OPERATION_DIRECTION:
|
||||
case PROP_STATE_ESCALATOR_FAULT:
|
||||
case PROP_STATE_ESCALATOR_MODE:
|
||||
case PROP_STATE_LIFT_CAR_DIRECTION:
|
||||
case PROP_STATE_LIFT_CAR_DOOR_COMMAND:
|
||||
case PROP_STATE_LIFT_CAR_DRIVE_STATUS:
|
||||
case PROP_STATE_LIFT_CAR_MODE:
|
||||
case PROP_STATE_LIFT_GROUP_MODE:
|
||||
case PROP_STATE_LIFT_FAULT:
|
||||
case PROP_STATE_AUDIT_LEVEL:
|
||||
case PROP_STATE_AUDIT_OPERATION:
|
||||
case PROP_STATE_EXTENDED_VALUE:
|
||||
case PROP_STATE_DOOR_ALARM_STATE:
|
||||
case PROP_STATE_UNSIGNED_VALUE:
|
||||
default:
|
||||
status = bacnet_string_to_uint32(search_name, found_index);
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For a given enumerated object property string,
|
||||
* find the enumeration value
|
||||
|
||||
@@ -242,6 +242,15 @@ const char *bactext_timer_transition_name(uint32_t index);
|
||||
BACNET_STACK_EXPORT
|
||||
const char *bactext_timer_state_name(uint32_t index);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
const char *bactext_boolean_value_name(uint32_t index);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool bactext_property_states_strtoul(
|
||||
BACNET_PROPERTY_STATES object_property,
|
||||
const char *search_name,
|
||||
uint32_t *found_index);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool bactext_object_property_strtoul(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "bacnet/timestamp.h"
|
||||
#include "bacnet/authentication_factor.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
#include "bacnet/bactext.h"
|
||||
|
||||
/** @file event.c Encode/Decode Event Notifications */
|
||||
|
||||
@@ -3114,3 +3115,264 @@ int event_notify_decode_service_request(
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief parse a list of strings for the event notification:
|
||||
* @details event-notification string:
|
||||
* process-id initiating-device-id event-object-type event-object-instance
|
||||
* sequence-number notification-class priority message-text notify-type
|
||||
* ack-required from-state to-state event-type
|
||||
* [change-of-bitstring reference-bit-string status-flags]
|
||||
* [change-of-state new-state-tag new-state-value status-flags]
|
||||
* @param data [out] BACnetEventNotification data to store parsed data
|
||||
* @param argc [in] number of arguments in argv
|
||||
* @param argv [in] array of strings to parse
|
||||
* @return true if successful, false if error
|
||||
*/
|
||||
bool event_notify_parse(
|
||||
BACNET_EVENT_NOTIFICATION_DATA *data, int argc, char *argv[])
|
||||
{
|
||||
int argi = 0;
|
||||
unsigned int target_args = 1;
|
||||
uint32_t found_index = 0;
|
||||
unsigned long long_value = 0;
|
||||
BACNET_PROPERTY_STATES tag = PROP_STATE_BOOLEAN_VALUE;
|
||||
BACNET_BIT_STRING *pBitString = NULL;
|
||||
|
||||
for (argi = 1; argi < argc; argi++) {
|
||||
if (target_args == 1) {
|
||||
/* process-id */
|
||||
if (!bacnet_string_to_uint32(
|
||||
argv[argi], &data->processIdentifier)) {
|
||||
return false;
|
||||
}
|
||||
target_args++;
|
||||
} else if (target_args == 2) {
|
||||
/* initiating-device-id */
|
||||
data->initiatingObjectIdentifier.type = OBJECT_DEVICE;
|
||||
if (!bacnet_strtoul(argv[argi], &long_value)) {
|
||||
return false;
|
||||
}
|
||||
if (long_value > BACNET_MAX_INSTANCE) {
|
||||
return false;
|
||||
}
|
||||
data->initiatingObjectIdentifier.instance = (uint32_t)long_value;
|
||||
target_args++;
|
||||
} else if (target_args == 3) {
|
||||
/* event-object-type */
|
||||
if (!bactext_object_type_strtol(argv[argi], &found_index)) {
|
||||
return false;
|
||||
}
|
||||
data->eventObjectIdentifier.type = (BACNET_OBJECT_TYPE)found_index;
|
||||
target_args++;
|
||||
} else if (target_args == 4) {
|
||||
/* event-object-instance */
|
||||
if (!bacnet_strtoul(argv[argi], &long_value)) {
|
||||
return false;
|
||||
}
|
||||
if (long_value > BACNET_MAX_INSTANCE) {
|
||||
return false;
|
||||
}
|
||||
data->eventObjectIdentifier.instance = (uint32_t)long_value;
|
||||
target_args++;
|
||||
} else if (target_args == 5) {
|
||||
/* sequence-number */
|
||||
if (!bacnet_string_to_uint16(
|
||||
argv[argi], &data->timeStamp.value.sequenceNum)) {
|
||||
return false;
|
||||
}
|
||||
data->timeStamp.tag = TIME_STAMP_SEQUENCE;
|
||||
target_args++;
|
||||
} else if (target_args == 6) {
|
||||
/* notification-class */
|
||||
if (!bacnet_string_to_uint32(
|
||||
argv[argi], &data->notificationClass)) {
|
||||
return false;
|
||||
}
|
||||
target_args++;
|
||||
} else if (target_args == 7) {
|
||||
/* priority */
|
||||
if (!bacnet_string_to_uint8(argv[argi], &data->priority)) {
|
||||
return false;
|
||||
}
|
||||
target_args++;
|
||||
} else if (target_args == 8) {
|
||||
/* message-text */
|
||||
if (!characterstring_init_ansi(data->messageText, argv[argi])) {
|
||||
return false;
|
||||
}
|
||||
target_args++;
|
||||
} else if (target_args == 9) {
|
||||
/* notify-type */
|
||||
if (!bactext_notify_type_strtol(argv[argi], &found_index)) {
|
||||
return false;
|
||||
}
|
||||
data->notifyType = (BACNET_NOTIFY_TYPE)found_index;
|
||||
target_args++;
|
||||
} else if (target_args == 10) {
|
||||
/* ack-required */
|
||||
if (!bacnet_string_to_bool(argv[argi], &data->ackRequired)) {
|
||||
return false;
|
||||
}
|
||||
target_args++;
|
||||
} else if (target_args == 11) {
|
||||
/* from-state */
|
||||
if (!bactext_event_state_strtol(argv[argi], &found_index)) {
|
||||
return false;
|
||||
}
|
||||
data->fromState = (BACNET_EVENT_STATE)found_index;
|
||||
target_args++;
|
||||
} else if (target_args == 12) {
|
||||
/* to-state */
|
||||
if (!bactext_event_state_strtol(argv[argi], &found_index)) {
|
||||
return false;
|
||||
}
|
||||
data->toState = (BACNET_EVENT_STATE)found_index;
|
||||
target_args++;
|
||||
} else if (target_args == 13) {
|
||||
/* event-type */
|
||||
if (!bactext_event_type_strtol(argv[argi], &found_index)) {
|
||||
return false;
|
||||
}
|
||||
data->eventType = (BACNET_EVENT_TYPE)found_index;
|
||||
target_args++;
|
||||
} else {
|
||||
if (data->eventType == EVENT_CHANGE_OF_BITSTRING) {
|
||||
if (target_args == 14) {
|
||||
pBitString = &data->notificationParams.changeOfBitstring
|
||||
.referencedBitString;
|
||||
bitstring_init_ascii(pBitString, argv[argi]);
|
||||
target_args++;
|
||||
} else if (target_args == 15) {
|
||||
pBitString =
|
||||
&data->notificationParams.changeOfBitstring.statusFlags;
|
||||
bitstring_init_ascii(pBitString, argv[argi]);
|
||||
target_args++;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (data->eventType == EVENT_CHANGE_OF_STATE) {
|
||||
if (target_args == 14) {
|
||||
if (!bacnet_strtoul(argv[argi], &long_value)) {
|
||||
return false;
|
||||
}
|
||||
tag = (BACNET_PROPERTY_STATES)long_value;
|
||||
data->notificationParams.changeOfState.newState.tag = tag;
|
||||
target_args++;
|
||||
} else if (target_args == 15) {
|
||||
if (!bactext_property_states_strtoul(
|
||||
tag, argv[argi], &found_index)) {
|
||||
return false;
|
||||
}
|
||||
if (tag == PROP_STATE_BOOLEAN_VALUE) {
|
||||
if (found_index) {
|
||||
data->notificationParams.changeOfState.newState
|
||||
.state.booleanValue = true;
|
||||
} else {
|
||||
data->notificationParams.changeOfState.newState
|
||||
.state.booleanValue = false;
|
||||
}
|
||||
} else if (tag == PROP_STATE_BINARY_VALUE) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.binaryValue = (BACNET_BINARY_PV)found_index;
|
||||
} else if (tag == PROP_STATE_EVENT_TYPE) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.eventType = (BACNET_EVENT_TYPE)found_index;
|
||||
} else if (tag == PROP_STATE_POLARITY) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.polarity = (BACNET_POLARITY)found_index;
|
||||
} else if (tag == PROP_STATE_PROGRAM_CHANGE) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.programChange =
|
||||
(BACNET_PROGRAM_REQUEST)found_index;
|
||||
} else if (tag == PROP_STATE_PROGRAM_STATE) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.programState = (BACNET_PROGRAM_STATE)found_index;
|
||||
} else if (tag == PROP_STATE_REASON_FOR_HALT) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.programError = (BACNET_PROGRAM_ERROR)found_index;
|
||||
} else if (tag == PROP_STATE_RELIABILITY) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.reliability = (BACNET_RELIABILITY)found_index;
|
||||
} else if (tag == PROP_STATE_EVENT_STATE) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.state = (BACNET_EVENT_STATE)found_index;
|
||||
} else if (tag == PROP_STATE_SYSTEM_STATUS) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.systemStatus = (BACNET_DEVICE_STATUS)found_index;
|
||||
} else if (tag == PROP_STATE_UNITS) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.units = (BACNET_ENGINEERING_UNITS)found_index;
|
||||
} else if (tag == PROP_STATE_UNSIGNED_VALUE) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.unsignedValue =
|
||||
(BACNET_UNSIGNED_INTEGER)found_index;
|
||||
} else if (tag == PROP_STATE_LIFE_SAFETY_MODE) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.lifeSafetyMode =
|
||||
(BACNET_LIFE_SAFETY_MODE)found_index;
|
||||
} else if (tag == PROP_STATE_LIFE_SAFETY_STATE) {
|
||||
data->notificationParams.changeOfState.newState.state
|
||||
.lifeSafetyState =
|
||||
(BACNET_LIFE_SAFETY_STATE)found_index;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
target_args++;
|
||||
} else if (target_args == 16) {
|
||||
pBitString =
|
||||
&data->notificationParams.changeOfState.statusFlags;
|
||||
bitstring_init_ascii(pBitString, argv[argi]);
|
||||
target_args++;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (data->eventType == EVENT_CHANGE_OF_VALUE) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_COMMAND_FAILURE) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_FLOATING_LIMIT) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_OUT_OF_RANGE) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_CHANGE_OF_LIFE_SAFETY) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_EXTENDED) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_BUFFER_READY) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_UNSIGNED_RANGE) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_ACCESS_EVENT) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_DOUBLE_OUT_OF_RANGE) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_SIGNED_OUT_OF_RANGE) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_UNSIGNED_OUT_OF_RANGE) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_CHANGE_OF_CHARACTERSTRING) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_CHANGE_OF_STATUS_FLAGS) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_CHANGE_OF_RELIABILITY) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_NONE) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_CHANGE_OF_DISCRETE_VALUE) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (data->eventType == EVENT_CHANGE_OF_TIMER) {
|
||||
/* FIXME: add event type parameters */
|
||||
} else if (
|
||||
(data->eventType >= EVENT_PROPRIETARY_MIN) &&
|
||||
(data->eventType <= EVENT_PROPRIETARY_MAX)) {
|
||||
/* Enumerated values 64-65535 may
|
||||
be used by others subject to
|
||||
the procedures and constraints
|
||||
described in Clause 23. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -471,6 +471,10 @@ int uevent_notify_send(
|
||||
BACNET_EVENT_NOTIFICATION_DATA *data,
|
||||
BACNET_ADDRESS *dest);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool event_notify_parse(
|
||||
BACNET_EVENT_NOTIFICATION_DATA *data, int argc, char *argv[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
Reference in New Issue
Block a user