void test_ReinitializeDevice( Test * pTest) { uint8_t apdu[480] = { 0 }; int len = 0; int apdu_len = 0; uint8_t invoke_id = 128; uint8_t test_invoke_id = 0; BACNET_REINITIALIZED_STATE state; BACNET_REINITIALIZED_STATE test_state; BACNET_CHARACTER_STRING password; BACNET_CHARACTER_STRING test_password; state = BACNET_REINIT_WARMSTART; characterstring_init_ansi(&password, "John 3:16"); len = rd_encode_apdu(&apdu[0], invoke_id, state, &password); ct_test(pTest, len != 0); apdu_len = len; len = rd_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_state, &test_password); ct_test(pTest, len != -1); ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, test_state == state); ct_test(pTest, characterstring_same(&test_password, &password)); return; }
void testWhoHas( Test * pTest) { BACNET_WHO_HAS_DATA data; data.low_limit = -1; data.high_limit = -1; data.object_name = false; data.object.identifier.type = OBJECT_ANALOG_INPUT; data.object.identifier.instance = 1; testWhoHasData(pTest, &data); for (data.low_limit = 0; data.low_limit <= BACNET_MAX_INSTANCE; data.low_limit += (BACNET_MAX_INSTANCE / 4)) { for (data.high_limit = 0; data.high_limit <= BACNET_MAX_INSTANCE; data.high_limit += (BACNET_MAX_INSTANCE / 4)) { data.object_name = false; for (data.object.identifier.type = OBJECT_ANALOG_INPUT; data.object.identifier.type <= MAX_BACNET_OBJECT_TYPE; data.object.identifier.type++) { for (data.object.identifier.instance = 1; data.object.identifier.instance <= BACNET_MAX_INSTANCE; data.object.identifier.instance <<= 1) { testWhoHasData(pTest, &data); } } data.object_name = true; characterstring_init_ansi(&data.object.name, "patricia"); testWhoHasData(pTest, &data); } } }
void testLSO( Test * pTest) { uint8_t apdu[1000]; int len; BACNET_LSO_DATA data; BACNET_LSO_DATA rxdata; memset(&rxdata, 0, sizeof(rxdata)); characterstring_init_ansi(&data.requestingSrc, "foobar"); data.operation = LIFE_SAFETY_OP_RESET; data.processId = 0x1234; data.targetObject.instance = 0x1000; data.targetObject.type = OBJECT_BINARY_INPUT; len = lso_encode_apdu(apdu, 100, &data); lso_decode_service_request(&apdu[4], len, &rxdata); ct_test(pTest, data.operation == rxdata.operation); ct_test(pTest, data.processId == rxdata.processId); ct_test(pTest, data.targetObject.instance == rxdata.targetObject.instance); ct_test(pTest, data.targetObject.type == rxdata.targetObject.type); ct_test(pTest, memcmp(data.requestingSrc.value, rxdata.requestingSrc.value, rxdata.requestingSrc.length) == 0); }
bool Routed_Device_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { DEVICE_OBJECT_DATA *pDev = &Devices[iCurrent_Device_Idx]; if (object_instance == pDev->bacObj.Object_Instance_Number) { return characterstring_init_ansi(object_name, pDev->bacObj.Object_Name); } return false; }
/** Manages ReadProperty service for fields which are different for routed * Devices, or hands off to the default Device RP function for the rest. * @param rpdata [in] Structure which describes the property to be read. * @return The length of the apdu encoded, or BACNET_STATUS_ERROR for error or * BACNET_STATUS_ABORT for abort message. */ int Routed_Device_Read_Property_Local( BACNET_READ_PROPERTY_DATA * rpdata) { int apdu_len = 0; /* return value */ BACNET_CHARACTER_STRING char_string; uint8_t *apdu = NULL; DEVICE_OBJECT_DATA *pDev = &Devices[iCurrent_Device_Idx]; if ((rpdata == NULL) || (rpdata->application_data == NULL) || (rpdata->application_data_len == 0)) { return 0; } apdu = rpdata->application_data; switch (rpdata->object_property) { case PROP_OBJECT_IDENTIFIER: apdu_len = encode_application_object_id(&apdu[0], OBJECT_DEVICE, pDev->bacObj.Object_Instance_Number); break; case PROP_OBJECT_NAME: characterstring_init_ansi(&char_string, pDev->bacObj.Object_Name); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; case PROP_DESCRIPTION: characterstring_init_ansi(&char_string, pDev->Description); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; case PROP_DATABASE_REVISION: apdu_len = encode_application_unsigned(&apdu[0], pDev->Database_Revision); break; default: apdu_len = Device_Read_Property_Local(rpdata); break; } return (apdu_len); }
/* note: the object name must be unique within this device */ bool Life_Safety_Point_Object_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { static char text_string[32] = ""; /* okay for single thread */ bool status = false; if (object_instance < MAX_LIFE_SAFETY_POINTS) { sprintf(text_string, "LS POINT %u", object_instance); status = characterstring_init_ansi(object_name, text_string); } return status; }
/* note: the object name must be unique within this device */ bool Binary_Output_Object_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { static char text_string[32]; /* okay for single thread */ bool status = false; if (object_instance < MAX_BINARY_OUTPUTS) { sprintf(text_string, "BO-%lu", object_instance); status = characterstring_init_ansi(object_name, text_string); } return status; }
bool bacfile_object_name( uint32_t instance, BACNET_CHARACTER_STRING * object_name) { bool status = false; char *filename = NULL; filename = bacfile_name(instance); if (filename) { status = characterstring_init_ansi(object_name, filename); } return status; }
/* note: the object name must be unique within this device */ bool Binary_Output_Object_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { static char text_string[16] = "BO-0"; /* okay for single thread */ bool status = false; if (object_instance < MAX_BINARY_OUTPUTS) { text_string[3] = '0' + (uint8_t) object_instance; status = characterstring_init_ansi(object_name, text_string); } return status; }
/* note: the object name must be unique within this device */ bool Multistate_Output_Object_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { static char text_string[32] = ""; /* okay for single thread */ bool status = false; if (object_instance < MAX_MULTISTATE_OUTPUTS) { sprintf(text_string, "MULTISTATE OUTPUT %u", object_instance); status = characterstring_init_ansi(object_name, text_string); } return status; }
bool Analog_Value_Object_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { static char text_string[16] = "AV-0"; /* okay for single thread */ bool status = false; if (object_instance < MAX_ANALOG_VALUES) { text_string[3] = '0' + (uint8_t) object_instance; status = characterstring_init_ansi(object_name, text_string); } return status; }
bool Multistate_Input_Object_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { unsigned index = 0; /* offset from instance lookup */ bool status = false; index = Multistate_Input_Instance_To_Index(object_instance); if (index < MAX_MULTISTATE_INPUTS) { status = characterstring_init_ansi(object_name, Object_Name[index]); } return status; }
bool Schedule_Object_Name(uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { static char text_string[32] = ""; /* okay for single thread */ unsigned int index; bool status = false; index = Schedule_Instance_To_Index(object_instance); if (index < MAX_SCHEDULES) { sprintf(text_string, "SCHEDULE %lu", (unsigned long) index); status = characterstring_init_ansi(object_name, text_string); } return status; }
/* note: the object name must be unique within this device */ bool Binary_Value_Object_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { static char text_string[32] = ""; /* okay for single thread */ bool status = false; if (object_instance < MAX_BINARY_VALUES) { sprintf(text_string, "BINARY VALUE %lu", (unsigned long) object_instance); status = characterstring_init_ansi(object_name, text_string); } return status; }
/* note: the object name must be unique within this device */ bool Credential_Data_Input_Object_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { static char text_string[32] = ""; /* okay for single thread */ bool status = false; if (object_instance < MAX_CREDENTIAL_DATA_INPUTS) { sprintf(text_string, "CREDENTIAL DATA INPUT %lu", (unsigned long) object_instance); status = characterstring_init_ansi(object_name, text_string); } return status; }
bool Notification_Class_Object_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { static char text_string[32] = ""; /* okay for single thread */ unsigned int index; bool status = false; index = Notification_Class_Instance_To_Index(object_instance); if (index < MAX_NOTIFICATION_CLASSES) { sprintf(text_string, "NOTIFICATION CLASS %lu", (unsigned long) index); status = characterstring_init_ansi(object_name, text_string); } return status; }
/** * For a given object instance-number, loads the object-name into * a characterstring. Note that the object name must be unique * within this device. * * @param object_instance - object-instance number of the object * @param object_name - holds the object-name retrieved * * @return true if object-name was retrieved */ bool Integer_Value_Object_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { char text_string[32] = ""; unsigned int index; bool status = false; index = Integer_Value_Instance_To_Index(object_instance); if (index < MAX_INTEGER_VALUES) { sprintf(text_string, "ANALOG VALUE %lu", (unsigned long) object_instance); status = characterstring_init_ansi(object_name, text_string); } return status; }
/** Initialize the Device Object. Initialize the group of object helper functions for any supported Object. Initialize each of the Device Object child Object instances. * @ingroup ObjIntf * @param object_table [in,out] array of structure with object functions. * Each Child Object must provide some implementation of each of these * functions in order to properly support the default handlers. */ void Device_Init( object_functions_t * object_table) { struct object_functions *pObject = NULL; characterstring_init_ansi(&My_Object_Name, "SimpleClient"); /* we don't use the object table passed in */ (void) object_table; pObject = &Object_Table[0]; while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { if (pObject->Object_Init) { pObject->Object_Init(); } pObject++; } }
bool Analog_Input_Object_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { static char text_string[32]; /* okay for single thread */ bool status = false; unsigned index = 0; index = Analog_Input_Instance_To_Index(object_instance); if (index < MAX_ANALOG_INPUTS) { sprintf(text_string, "AI-%lu", object_instance); status = characterstring_init_ansi(object_name, text_string); } return status; }
/** * For a given object instance-number, loads the object-name into * a characterstring. Note that the object name must be unique * within this device. * * @param object_instance - object-instance number of the object * @param object_name - holds the object-name retrieved * * @return true if object-name was retrieved */ bool Lighting_Output_Object_Name( uint32_t object_instance, BACNET_CHARACTER_STRING * object_name) { char text_string[32] = ""; bool status = false; unsigned index = 0; index = Lighting_Output_Instance_To_Index(object_instance); if (index < MAX_LIGHTING_OUTPUTS) { sprintf(text_string, "LIGHTING OUTPUT %lu", (unsigned long) object_instance); status = characterstring_init_ansi(object_name, text_string); } return status; }
void bacnet_name(uint16_t offset, BACNET_CHARACTER_STRING * char_string, char *default_string) { uint8_t encoding = 0; uint8_t length = 0; char name[NVM_NAME_SIZE + 1] = ""; nvm_read(NVM_NAME_ENCODING(offset), &encoding, 1); nvm_read(NVM_NAME_LENGTH(offset), &length, 1); nvm_read(NVM_NAME_STRING(offset), (uint8_t *) & name[0], NVM_NAME_SIZE); if (bacnet_name_isvalid(encoding, length, name)) { characterstring_init(char_string, encoding, &name[0], length); } else if (default_string) { characterstring_init_ansi(char_string, default_string); } }
/** Send a Who-Has request for a device which has a named Object. * @ingroup DMDOB * If low_limit and high_limit both are -1, then the device ID range is unlimited. * If low_limit and high_limit have the same non-negative value, then only * that device will respond. * Otherwise, low_limit must be less than high_limit for a range. * @param low_limit [in] Device Instance Low Range, 0 - 4,194,303 or -1 * @param high_limit [in] Device Instance High Range, 0 - 4,194,303 or -1 * @param object_name [in] The Name of the desired Object. */ void Send_WhoHas_Name( int32_t low_limit, int32_t high_limit, const char *object_name) { int len = 0; int pdu_len = 0; BACNET_ADDRESS dest; int bytes_sent = 0; BACNET_WHO_HAS_DATA data; BACNET_NPDU_DATA npdu_data; BACNET_ADDRESS my_address; /* if we are forbidden to send, don't send! */ if (!dcc_communication_enabled()) return; /* Who-Has is a global broadcast */ datalink_get_broadcast_address(&dest); datalink_get_my_address(&my_address); /* encode the NPDU portion of the packet */ npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest, &my_address, &npdu_data); /* encode the APDU portion of the packet */ data.low_limit = low_limit; data.high_limit = high_limit; data.is_object_name = true; characterstring_init_ansi(&data.object.name, object_name); len = whohas_encode_apdu(&Handler_Transmit_Buffer[pdu_len], &data); pdu_len += len; /* send the data */ bytes_sent = datalink_send_pdu(&dest, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); #if PRINT_ENABLED if (bytes_sent <= 0) fprintf(stderr, "Failed to Send Who-Has Request (%s)!\n", strerror(errno)); #endif }
void Device_Init( object_functions_t * object_table) { struct my_object_functions *pObject = NULL; /* we don't use the object table passed in since there is extra stuff we don't need in there. */ (void) object_table; /* our local object table */ pObject = &Object_Table[0]; while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { if (pObject->Object_Init) { pObject->Object_Init(); } pObject++; } dcc_set_status_duration(COMMUNICATION_ENABLE, 0); Object_Instance_Number = 12345; characterstring_init_ansi(&My_Object_Name, "ARM7 Demo Device"); }
void testIHave( Test * pTest) { BACNET_I_HAVE_DATA data; characterstring_init_ansi(&data.object_name, "Patricia - my love!"); data.device_id.type = OBJECT_DEVICE; for (data.device_id.instance = 1; data.device_id.instance <= BACNET_MAX_INSTANCE; data.device_id.instance <<= 1) { for (data.object_id.type = OBJECT_ANALOG_INPUT; data.object_id.type < MAX_BACNET_OBJECT_TYPE; data.object_id.type++) { for (data.object_id.instance = 1; data.object_id.instance <= BACNET_MAX_INSTANCE; data.object_id.instance <<= 1) { testIHaveData(pTest, &data); } } } }
/* find a specific device, or use -1 for limit if you want unlimited */ void Send_I_Have( uint32_t device_id, BACNET_OBJECT_TYPE object_type, uint32_t object_instance, char *object_name) { int len = 0; int pdu_len = 0; BACNET_ADDRESS dest; int bytes_sent = 0; BACNET_I_HAVE_DATA data; BACNET_NPDU_DATA npdu_data; /* if we are forbidden to send, don't send! */ if (!dcc_communication_enabled()) return; /* Who-Has is a global broadcast */ datalink_get_broadcast_address(&dest); /* encode the NPDU portion of the packet */ npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL); pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest, NULL, &npdu_data); /* encode the APDU portion of the packet */ data.device_id.type = OBJECT_DEVICE; data.device_id.instance = device_id; data.object_id.type = object_type; data.object_id.instance = object_instance; characterstring_init_ansi(&data.object_name, object_name); len = ihave_encode_apdu(&Handler_Transmit_Buffer[pdu_len], &data); pdu_len += len; /* send the data */ bytes_sent = datalink_send_pdu(&dest, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); #if PRINT_ENABLED if (bytes_sent <= 0) fprintf(stderr, "Failed to Send I-Have Reply (%s)!\n", strerror(errno)); #endif }
void Device_Init( object_functions_t * object_table) { struct my_object_functions *pObject = NULL; /* we don't use the object table passed in since there is extra stuff we don't need in there. */ (void) object_table; /* our local object table */ pObject = &Object_Table[0]; while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { if (pObject->Object_Init) { pObject->Object_Init(); } pObject++; } dcc_set_status_duration(COMMUNICATION_ENABLE, 0); if (Object_Instance_Number >= BACNET_MAX_INSTANCE) { Object_Instance_Number = 103; srand(Object_Instance_Number); } characterstring_init_ansi(&My_Object_Name, "stm32-design-challenge-103"); }
/* return the length of the apdu encoded or BACNET_STATUS_ERROR for error */ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA * rpdata) { int apdu_len = 0; /* return value */ int len = 0; /* apdu len intermediate value */ BACNET_BIT_STRING bit_string = { 0 }; BACNET_CHARACTER_STRING char_string = { 0 }; unsigned i = 0; int object_type = 0; uint32_t instance = 0; unsigned count = 0; uint8_t *apdu = NULL; struct my_object_functions *pObject = NULL; if ((rpdata->application_data == NULL) || (rpdata->application_data_len == 0)) { return 0; } apdu = rpdata->application_data; switch ((int) rpdata->object_property) { case PROP_OBJECT_IDENTIFIER: apdu_len = encode_application_object_id(&apdu[0], rpdata->object_type, rpdata->object_instance); break; case PROP_OBJECT_NAME: Device_Object_Name(rpdata->object_instance, &char_string); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; case PROP_OBJECT_TYPE: apdu_len = encode_application_enumerated(&apdu[0], rpdata->object_type); break; case PROP_DESCRIPTION: bacnet_name(NVM_DEVICE_DESCRIPTION, &char_string, "default description"); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; case PROP_LOCATION: bacnet_name(NVM_DEVICE_LOCATION, &char_string, "default location"); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; case PROP_SYSTEM_STATUS: apdu_len = encode_application_enumerated(&apdu[0], Device_System_Status()); break; case PROP_VENDOR_NAME: characterstring_init_ansi(&char_string, Device_Vendor_Name()); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; case PROP_VENDOR_IDENTIFIER: apdu_len = encode_application_unsigned(&apdu[0], BACNET_VENDOR_ID); break; case PROP_MODEL_NAME: characterstring_init_ansi(&char_string, Device_Model_Name()); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; case PROP_FIRMWARE_REVISION: characterstring_init_ansi(&char_string, Device_Firmware_Revision()); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; case PROP_APPLICATION_SOFTWARE_VERSION: characterstring_init_ansi(&char_string, Device_Application_Software_Version()); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; case PROP_PROTOCOL_VERSION: apdu_len = encode_application_unsigned(&apdu[0], BACNET_PROTOCOL_VERSION); break; case PROP_PROTOCOL_REVISION: apdu_len = encode_application_unsigned(&apdu[0], BACNET_PROTOCOL_REVISION); break; case PROP_PROTOCOL_SERVICES_SUPPORTED: /* Note: list of services that are executed, not initiated. */ bitstring_init(&bit_string); for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) { /* automatic lookup based on handlers set */ bitstring_set_bit(&bit_string, (uint8_t) i, apdu_service_supported((BACNET_SERVICES_SUPPORTED) i)); } apdu_len = encode_application_bitstring(&apdu[0], &bit_string); break; case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED: /* Note: this is the list of objects that can be in this device, not a list of objects that this device can access */ bitstring_init(&bit_string); for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) { /* initialize all the object types to not-supported */ bitstring_set_bit(&bit_string, (uint8_t) i, false); } /* set the object types with objects to supported */ i = 0; pObject = &Object_Table[i]; while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { if ((pObject->Object_Count) && (pObject->Object_Count() > 0)) { bitstring_set_bit(&bit_string, pObject->Object_Type, true); } pObject++; } apdu_len = encode_application_bitstring(&apdu[0], &bit_string); break; case PROP_OBJECT_LIST: count = Device_Object_List_Count(); /* Array element zero is the number of objects in the list */ if (rpdata->array_index == 0) apdu_len = encode_application_unsigned(&apdu[0], count); /* if no index was specified, then try to encode the entire list */ /* into one packet. Note that more than likely you will have */ /* to return an error if the number of encoded objects exceeds */ /* your maximum APDU size. */ else if (rpdata->array_index == BACNET_ARRAY_ALL) { for (i = 1; i <= count; i++) { if (Device_Object_List_Identifier(i, &object_type, &instance)) { len = encode_application_object_id(&apdu[apdu_len], object_type, instance); apdu_len += len; /* assume next one is the same size as this one */ /* can we all fit into the APDU? */ if ((apdu_len + len) >= MAX_APDU) { /* Abort response */ rpdata->error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; apdu_len = BACNET_STATUS_ABORT; break; } } else { /* error: internal error? */ rpdata->error_class = ERROR_CLASS_SERVICES; rpdata->error_code = ERROR_CODE_OTHER; apdu_len = BACNET_STATUS_ERROR; break; } } } else { if (Device_Object_List_Identifier(rpdata->array_index, &object_type, &instance)) apdu_len = encode_application_object_id(&apdu[0], object_type, instance); else { rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; apdu_len = BACNET_STATUS_ERROR; } } break; case PROP_MAX_APDU_LENGTH_ACCEPTED: apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU); break; case PROP_SEGMENTATION_SUPPORTED: apdu_len = encode_application_enumerated(&apdu[0], Device_Segmentation_Supported()); break; case PROP_APDU_TIMEOUT: apdu_len = encode_application_unsigned(&apdu[0], apdu_timeout()); break; case PROP_NUMBER_OF_APDU_RETRIES: apdu_len = encode_application_unsigned(&apdu[0], apdu_retries()); break; case PROP_DEVICE_ADDRESS_BINDING: /* FIXME: encode the list here, if it exists */ break; case PROP_DATABASE_REVISION: apdu_len = encode_application_unsigned(&apdu[0], Device_Database_Revision()); break; case PROP_MAX_INFO_FRAMES: apdu_len = encode_application_unsigned(&apdu[0], dlmstp_max_info_frames()); break; case PROP_MAX_MASTER: apdu_len = encode_application_unsigned(&apdu[0], dlmstp_max_master()); break; case 512: apdu_len = encode_application_unsigned(&apdu[0], stack_size()); break; case 513: apdu_len = encode_application_unsigned(&apdu[0], stack_unused()); break; default: rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; apdu_len = BACNET_STATUS_ERROR; break; } /* only array properties can have array options */ if ((apdu_len >= 0) && (rpdata->object_property != PROP_OBJECT_LIST) && (rpdata->array_index != BACNET_ARRAY_ALL)) { rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; apdu_len = BACNET_STATUS_ERROR; } return apdu_len; }
/* assumption - object already exists, and has been bounds checked */ int Binary_Input_Encode_Property_APDU( uint8_t * apdu, uint32_t object_instance, BACNET_PROPERTY_ID property, int32_t array_index, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code) { int apdu_len = 0; /* return value */ BACNET_BIT_STRING bit_string; BACNET_CHARACTER_STRING char_string; BACNET_POLARITY polarity = POLARITY_NORMAL; BACNET_BINARY_PV value = BINARY_INACTIVE; (void) array_index; Binary_Input_Initialize(); switch (property) { case PROP_OBJECT_IDENTIFIER: apdu_len = encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT, object_instance); break; case PROP_OBJECT_NAME: case PROP_DESCRIPTION: /* note: object name must be unique in our device */ characterstring_init_ansi(&char_string, Binary_Input_Name(object_instance)); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; case PROP_OBJECT_TYPE: apdu_len = encode_application_enumerated(&apdu[0], OBJECT_BINARY_INPUT); break; case PROP_PRESENT_VALUE: value = Binary_Input_Present_Value(object_instance); apdu_len = encode_application_enumerated(&apdu[0], value); break; case PROP_STATUS_FLAGS: /* note: see the details in the standard on how to use these */ bitstring_init(&bit_string); bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false); bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false); bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false); bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false); apdu_len = encode_application_bitstring(&apdu[0], &bit_string); break; case PROP_EVENT_STATE: /* note: see the details in the standard on how to use this */ apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL); break; case PROP_OUT_OF_SERVICE: apdu_len = encode_application_boolean(&apdu[0], false); break; case PROP_POLARITY: apdu_len = encode_application_enumerated(&apdu[0], polarity); break; default: *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_UNKNOWN_PROPERTY; apdu_len = -1; break; } return apdu_len; }
void testAlarmAck( Test * pTest) { BACNET_ALARM_ACK_DATA testAlarmAckIn; BACNET_ALARM_ACK_DATA testAlarmAckOut; uint8_t buffer[MAX_APDU]; int inLen; int outLen; testAlarmAckIn.ackProcessIdentifier = 0x1234; characterstring_init_ansi(&testAlarmAckIn.ackSource, "This is a test"); testAlarmAckIn.ackTimeStamp.tag = TIME_STAMP_SEQUENCE; testAlarmAckIn.ackTimeStamp.value.sequenceNum = 0x4331; testAlarmAckIn.eventObjectIdentifier.instance = 567; testAlarmAckIn.eventObjectIdentifier.type = OBJECT_DEVICE; testAlarmAckIn.eventTimeStamp.tag = TIME_STAMP_TIME; testAlarmAckIn.eventTimeStamp.value.time.hour = 10; testAlarmAckIn.eventTimeStamp.value.time.min = 11; testAlarmAckIn.eventTimeStamp.value.time.sec = 12; testAlarmAckIn.eventTimeStamp.value.time.hundredths = 14; testAlarmAckIn.eventStateAcked = EVENT_STATE_OFFNORMAL; memset(&testAlarmAckOut, 0, sizeof(testAlarmAckOut)); inLen = alarm_ack_encode_service_request(buffer, &testAlarmAckIn); outLen = alarm_ack_decode_service_request(buffer, inLen, &testAlarmAckOut); ct_test(pTest, inLen == outLen); ct_test(pTest, testAlarmAckIn.ackProcessIdentifier == testAlarmAckOut.ackProcessIdentifier); ct_test(pTest, testAlarmAckIn.ackTimeStamp.tag == testAlarmAckOut.ackTimeStamp.tag); ct_test(pTest, testAlarmAckIn.ackTimeStamp.value.sequenceNum == testAlarmAckOut.ackTimeStamp.value.sequenceNum); ct_test(pTest, testAlarmAckIn.ackProcessIdentifier == testAlarmAckOut.ackProcessIdentifier); ct_test(pTest, testAlarmAckIn.eventObjectIdentifier.instance == testAlarmAckOut.eventObjectIdentifier.instance); ct_test(pTest, testAlarmAckIn.eventObjectIdentifier.type == testAlarmAckOut.eventObjectIdentifier.type); ct_test(pTest, testAlarmAckIn.eventTimeStamp.tag == testAlarmAckOut.eventTimeStamp.tag); ct_test(pTest, testAlarmAckIn.eventTimeStamp.value.time.hour == testAlarmAckOut.eventTimeStamp.value.time.hour); ct_test(pTest, testAlarmAckIn.eventTimeStamp.value.time.min == testAlarmAckOut.eventTimeStamp.value.time.min); ct_test(pTest, testAlarmAckIn.eventTimeStamp.value.time.sec == testAlarmAckOut.eventTimeStamp.value.time.sec); ct_test(pTest, testAlarmAckIn.eventTimeStamp.value.time.hundredths == testAlarmAckOut.eventTimeStamp.value.time.hundredths); ct_test(pTest, testAlarmAckIn.eventStateAcked == testAlarmAckOut.eventStateAcked); }
/* return apdu len, or BACNET_STATUS_ERROR on error */ int Multistate_Input_Read_Property( BACNET_READ_PROPERTY_DATA * rpdata) { int len = 0; int apdu_len = 0; /* return value */ BACNET_BIT_STRING bit_string; BACNET_CHARACTER_STRING char_string; uint32_t present_value = 0; unsigned i = 0; uint32_t max_states = 0; bool state = false; uint8_t *apdu = NULL; if ((rpdata == NULL) || (rpdata->application_data == NULL) || (rpdata->application_data_len == 0)) { return 0; } apdu = rpdata->application_data; switch (rpdata->object_property) { case PROP_OBJECT_IDENTIFIER: apdu_len = encode_application_object_id(&apdu[0], OBJECT_MULTI_STATE_INPUT, rpdata->object_instance); break; /* note: Name and Description don't have to be the same. You could make Description writable and different */ case PROP_OBJECT_NAME: Multistate_Input_Object_Name(rpdata->object_instance, &char_string); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; case PROP_DESCRIPTION: characterstring_init_ansi(&char_string, Multistate_Input_Description(rpdata->object_instance)); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; case PROP_OBJECT_TYPE: apdu_len = encode_application_enumerated(&apdu[0], OBJECT_MULTI_STATE_INPUT); break; case PROP_PRESENT_VALUE: present_value = Multistate_Input_Present_Value(rpdata->object_instance); apdu_len = encode_application_unsigned(&apdu[0], present_value); break; case PROP_STATUS_FLAGS: /* note: see the details in the standard on how to use these */ bitstring_init(&bit_string); bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false); bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false); bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false); if (Multistate_Input_Out_Of_Service(rpdata->object_instance)) { bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, true); } else { bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false); } apdu_len = encode_application_bitstring(&apdu[0], &bit_string); break; case PROP_EVENT_STATE: /* note: see the details in the standard on how to use this */ apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL); break; case PROP_OUT_OF_SERVICE: state = Multistate_Input_Out_Of_Service(rpdata->object_instance); apdu_len = encode_application_boolean(&apdu[0], state); break; case PROP_NUMBER_OF_STATES: apdu_len = encode_application_unsigned(&apdu[apdu_len], Multistate_Input_Max_States(rpdata->object_instance)); break; case PROP_STATE_TEXT: if (rpdata->array_index == 0) { /* Array element zero is the number of elements in the array */ apdu_len = encode_application_unsigned(&apdu[0], Multistate_Input_Max_States(rpdata->object_instance)); } else if (rpdata->array_index == BACNET_ARRAY_ALL) { /* if no index was specified, then try to encode the entire list */ /* into one packet. */ max_states = Multistate_Input_Max_States(rpdata->object_instance); for (i = 1; i <= max_states; i++) { characterstring_init_ansi(&char_string, Multistate_Input_State_Text(rpdata->object_instance, i)); /* FIXME: this might go beyond MAX_APDU length! */ len = encode_application_character_string(&apdu[apdu_len], &char_string); /* add it if we have room */ if ((apdu_len + len) < MAX_APDU) { apdu_len += len; } else { rpdata->error_class = ERROR_CLASS_SERVICES; rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT; apdu_len = BACNET_STATUS_ERROR; break; } } } else { max_states = Multistate_Input_Max_States(rpdata->object_instance); if (rpdata->array_index <= max_states) { characterstring_init_ansi(&char_string, Multistate_Input_State_Text(rpdata->object_instance, rpdata->array_index)); apdu_len = encode_application_character_string(&apdu[0], &char_string); } else { rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; apdu_len = BACNET_STATUS_ERROR; } } break; default: rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; apdu_len = BACNET_STATUS_ERROR; break; } /* only array properties can have array options */ if ((apdu_len >= 0) && (rpdata->object_property != PROP_STATE_TEXT) && (rpdata->array_index != BACNET_ARRAY_ALL)) { rpdata->error_class = ERROR_CLASS_PROPERTY; rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; apdu_len = BACNET_STATUS_ERROR; } return apdu_len; }