Indented.

This commit is contained in:
skarg
2007-11-29 15:56:53 +00:00
parent c585241c03
commit 411d6c1b24
236 changed files with 17864 additions and 15724 deletions
+27 -22
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -63,9 +63,11 @@ static char *Communication_Password = NULL;
static bool Error_Detected = false;
static void MyErrorHandler(BACNET_ADDRESS * src,
static void MyErrorHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void) src;
@@ -76,30 +78,34 @@ static void MyErrorHandler(BACNET_ADDRESS * src,
Error_Detected = true;
}
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason, bool server)
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
(void) server;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name(abort_reason));
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name(reject_reason));
printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
void MyDeviceCommunicationControlSimpleAckHandler(BACNET_ADDRESS * src,
void MyDeviceCommunicationControlSimpleAckHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id)
{
(void) src;
@@ -107,15 +113,14 @@ void MyDeviceCommunicationControlSimpleAckHandler(BACNET_ADDRESS * src,
printf("DeviceCommunicationControl Acknowledged!\r\n");
}
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
handler_i_am_bind);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
@@ -138,7 +143,9 @@ static void Init_Service_Handlers(void)
apdu_set_reject_handler(MyRejectHandler);
}
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
@@ -192,8 +199,7 @@ int main(int argc, char *argv[])
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
@@ -208,8 +214,7 @@ int main(int argc, char *argv[])
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds -
last_seconds) * 1000));
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
if (Error_Detected)
break;
/* wait until the device is bound, or timeout and quit */
+50 -49
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -69,56 +69,62 @@ static BACNET_RP_SERVICE_DATA Read_Property_Data;
/* FIXME: keep the object list in here */
/* static OS_Keylist Object_List; */
static void MyErrorHandler(BACNET_ADDRESS * src,
static void MyErrorHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
#if 1
#if 1
printf("BACnet Error: %s: %s\r\n",
bactext_error_class_name(error_class),
bactext_error_code_name(error_code));
#else
#else
(void) error_class;
(void) error_code;
#endif
#endif
Error_Detected = true;
}
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason, bool server)
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
(void) server;
#if 1
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name(abort_reason));
#else
#if 1
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason));
#else
(void) abort_reason;
#endif
#endif
Error_Detected = true;
}
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
#if 1
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name(reject_reason));
#else
#if 1
printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason));
#else
(void) reject_reason;
#endif
#endif
Error_Detected = true;
}
void PrintReadPropertyData(BACNET_READ_PROPERTY_DATA * data)
void PrintReadPropertyData(
BACNET_READ_PROPERTY_DATA * data)
{
BACNET_APPLICATION_DATA_VALUE value; /* for decode value data */
int len = 0;
@@ -170,16 +176,17 @@ void PrintReadPropertyData(BACNET_READ_PROPERTY_DATA * data)
}
}
void MyReadPropertyAckHandler(uint8_t * service_request,
void MyReadPropertyAckHandler(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
{
int len = 0;
BACNET_READ_PROPERTY_DATA data;
(void) src;
len = rp_ack_decode_service_request(service_request,
service_len, &data);
len = rp_ack_decode_service_request(service_request, service_len, &data);
if (len > 0) {
memmove(&Read_Property_Data.service_data, service_data, sizeof(data));
memmove(&Read_Property_Data.data, &data, sizeof(data));
@@ -187,15 +194,14 @@ void MyReadPropertyAckHandler(uint8_t * service_request,
}
}
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
handler_i_am_bind);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
@@ -207,13 +213,13 @@ static void Init_Service_Handlers(void)
apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_PROPERTY,
MyReadPropertyAckHandler);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY,
MyErrorHandler);
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
static uint8_t Read_Properties(uint32_t device_instance)
static uint8_t Read_Properties(
uint32_t device_instance)
{
uint8_t invoke_id = 0;
static unsigned index = 0;
@@ -226,12 +232,10 @@ static uint8_t Read_Properties(uint32_t device_instance)
}
if (pRequired[index] != -1) {
printf(" %s: ",bactext_property_name(pRequired[index]));
printf(" %s: ", bactext_property_name(pRequired[index]));
invoke_id = Send_Read_Property_Request(device_instance,
OBJECT_DEVICE,
device_instance,
pRequired[index],
BACNET_ARRAY_ALL);
device_instance, pRequired[index], BACNET_ARRAY_ALL);
if (invoke_id) {
index++;
}
@@ -240,7 +244,9 @@ static uint8_t Read_Properties(uint32_t device_instance)
return invoke_id;
}
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
@@ -257,9 +263,7 @@ int main(int argc, char *argv[])
/* print help if not enough arguments */
if (argc < 2) {
printf
("%s device-instance\r\n",
filename_remove_path(argv[0]));
printf("%s device-instance\r\n", filename_remove_path(argv[0]));
return 0;
}
@@ -267,7 +271,7 @@ int main(int argc, char *argv[])
Target_Device_Object_Instance = strtol(argv[1], 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+1);
Target_Device_Object_Instance, BACNET_MAX_INSTANCE + 1);
return 1;
}
/* setup my info */
@@ -281,8 +285,7 @@ int main(int argc, char *argv[])
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
printf("List of Objects in test device:\r\n");
printf("{\r\n");
/* loop forever */
@@ -299,8 +302,7 @@ int main(int argc, char *argv[])
}
/* at least one second has passed */
if (current_seconds != last_seconds) {
tsm_timer_milliseconds(((current_seconds -
last_seconds) * 1000));
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,
@@ -308,7 +310,7 @@ int main(int argc, char *argv[])
if (found) {
/* invoke ID is set to zero when it is not in use */
if (invoke_id == 0) {
invoke_id = Read_Properties(Target_Device_Object_Instance);
invoke_id = Read_Properties(Target_Device_Object_Instance);
if (invoke_id == 0) {
break;
}
@@ -321,8 +323,7 @@ int main(int argc, char *argv[])
}
} else if (tsm_invoke_id_free(invoke_id)) {
invoke_id = 0;
}
else if (tsm_invoke_id_failed(invoke_id)) {
} else if (tsm_invoke_id_failed(invoke_id)) {
fprintf(stderr, "\rError: TSM Timeout!\r\n");
tsm_free_invoke_id(invoke_id);
invoke_id = 0;
+7 -5
View File
@@ -40,7 +40,7 @@
#include "ai.h"
#include "ao.h"
#if defined(BACFILE)
#include "bacfile.h"
#include "bacfile.h"
#endif
/*
@@ -95,9 +95,11 @@ shall be TRUE, otherwise FALSE.
*/
#if defined(BACFILE)
void handler_atomic_read_file(uint8_t * service_request,
void handler_atomic_read_file(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_ATOMIC_READ_FILE_DATA data;
int len = 0;
@@ -125,7 +127,7 @@ void handler_atomic_read_file(uint8_t * service_request,
fprintf(stderr, "ARF: Segmented Message. Sending Abort!\n");
#endif
goto ARF_ABORT;
}
}
len = arf_decode_service_request(service_request, service_len, &data);
/* bad decoding - send an abort */
if (len < 0) {
@@ -186,7 +188,7 @@ void handler_atomic_read_file(uint8_t * service_request,
service_data->invoke_id,
SERVICE_CONFIRMED_ATOMIC_READ_FILE, error_class, error_code);
}
ARF_ABORT:
ARF_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+5 -4
View File
@@ -47,9 +47,11 @@
/* that someone can read from us. It is common to */
/* use the description as the file name. */
#if defined(BACFILE)
void handler_atomic_read_file_ack(uint8_t * service_request,
void handler_atomic_read_file_ack(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
{
int len = 0;
BACNET_ATOMIC_READ_FILE_DATA data;
@@ -60,8 +62,7 @@ void handler_atomic_read_file_ack(uint8_t * service_request,
(void) src;
/* get the file instance from the tsm data before freeing it */
instance = bacfile_instance_from_tsm(service_data->invoke_id);
len = arf_ack_decode_service_request(service_request,
service_len, &data);
len = arf_ack_decode_service_request(service_request, service_len, &data);
#if PRINT_ENABLED
fprintf(stderr, "Received Read-File Ack!\n");
#endif
+8 -6
View File
@@ -40,7 +40,7 @@
/* demo objects */
#include "device.h"
#if defined(BACFILE)
#include "bacfile.h"
#include "bacfile.h"
#endif
/*
@@ -73,9 +73,11 @@ standard.
*/
#if defined(BACFILE)
void handler_atomic_write_file(uint8_t * service_request,
void handler_atomic_write_file(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_ATOMIC_WRITE_FILE_DATA data;
int len = 0;
@@ -113,7 +115,7 @@ void handler_atomic_write_file(uint8_t * service_request,
fprintf(stderr, "Bad Encoding. Sending Abort!\n");
#endif
goto AWF_ABORT;
}
}
if (data.object_type == OBJECT_FILE) {
if (!bacfile_valid_instance(data.object_instance)) {
error = true;
@@ -126,7 +128,7 @@ void handler_atomic_write_file(uint8_t * service_request,
#endif
len =
awf_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
[pdu_len], service_data->invoke_id, &data);
} else {
error = true;
error_class = ERROR_CLASS_OBJECT;
@@ -151,7 +153,7 @@ void handler_atomic_write_file(uint8_t * service_request,
service_data->invoke_id,
SERVICE_CONFIRMED_ATOMIC_READ_FILE, error_class, error_code);
}
AWF_ABORT:
AWF_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+6 -4
View File
@@ -40,9 +40,11 @@
static char *My_Password = "filister";
void handler_device_communication_control(uint8_t * service_request,
void handler_device_communication_control(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
uint16_t timeDuration = 0;
BACNET_COMMUNICATION_ENABLE_DISABLE state = COMMUNICATION_ENABLE;
@@ -70,7 +72,7 @@ void handler_device_communication_control(uint8_t * service_request,
"Sending Abort - segmented message.\n");
#endif
goto DCC_ABORT;
}
}
/* decode the service request only */
len = dcc_decode_service_request(service_request,
service_len, &timeDuration, &state, &password);
@@ -121,7 +123,7 @@ void handler_device_communication_control(uint8_t * service_request,
#endif
}
}
DCC_ABORT:
DCC_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+8 -4
View File
@@ -32,8 +32,10 @@
#include "iam.h"
#include "address.h"
void handler_i_am_add(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
void handler_i_am_add(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
uint32_t device_id = 0;
@@ -61,8 +63,10 @@ void handler_i_am_add(uint8_t * service_request,
return;
}
void handler_i_am_bind(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
void handler_i_am_bind(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
uint32_t device_id = 0;
+5 -4
View File
@@ -32,16 +32,17 @@
#include "bactext.h"
#include "ihave.h"
void handler_i_have(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
void handler_i_have(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
BACNET_I_HAVE_DATA data;
(void) service_len;
(void) src;
len = ihave_decode_service_request(service_request,
service_len, &data);
len = ihave_decode_service_request(service_request, service_len, &data);
if (len != -1) {
#if PRINT_ENABLED
fprintf(stderr, "I-Have: %s %d from %s %u!\r\n",
+6 -4
View File
@@ -41,9 +41,11 @@
static char *Password = "Jesus";
static BACNET_CHARACTER_STRING My_Password;
void handler_reinitialize_device(uint8_t * service_request,
void handler_reinitialize_device(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_REINITIALIZED_STATE state;
BACNET_CHARACTER_STRING their_password;
@@ -70,7 +72,7 @@ void handler_reinitialize_device(uint8_t * service_request,
"ReinitializeDevice: Sending Abort - segmented message.\n");
#endif
goto RD_ABORT;
}
}
/* decode the service request only */
len = rd_decode_service_request(service_request,
service_len, &state, &their_password);
@@ -124,7 +126,7 @@ void handler_reinitialize_device(uint8_t * service_request,
#endif
}
}
RD_ABORT:
RD_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+32 -67
View File
@@ -47,7 +47,7 @@
#include "lsp.h"
#include "mso.h"
#if defined(BACFILE)
#include "bacfile.h"
#include "bacfile.h"
#endif
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
@@ -69,115 +69,82 @@ int Encode_Property_APDU(
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
/* handle each object type */
switch(object_type) {
switch (object_type) {
case OBJECT_DEVICE:
if (Device_Valid_Object_Instance_Number(object_instance)) {
apdu_len = Device_Encode_Property_APDU(
&apdu[0],
property,
array_index,
error_class, error_code);
apdu_len = Device_Encode_Property_APDU(&apdu[0],
property, array_index, error_class, error_code);
}
break;
case OBJECT_ANALOG_INPUT:
if (Analog_Input_Valid_Instance(object_instance)) {
apdu_len = Analog_Input_Encode_Property_APDU(
&apdu[0],
apdu_len = Analog_Input_Encode_Property_APDU(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
case OBJECT_ANALOG_OUTPUT:
if (Analog_Output_Valid_Instance(object_instance)) {
apdu_len = Analog_Output_Encode_Property_APDU(
&apdu[0],
apdu_len = Analog_Output_Encode_Property_APDU(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Valid_Instance(object_instance)) {
apdu_len = Analog_Value_Encode_Property_APDU(
&apdu[0],
apdu_len = Analog_Value_Encode_Property_APDU(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
case OBJECT_BINARY_INPUT:
if (Binary_Input_Valid_Instance(object_instance)) {
apdu_len = Binary_Input_Encode_Property_APDU(
&apdu[0],
apdu_len = Binary_Input_Encode_Property_APDU(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
case OBJECT_BINARY_OUTPUT:
if (Binary_Output_Valid_Instance(object_instance)) {
apdu_len = Binary_Output_Encode_Property_APDU(
&apdu[0],
apdu_len = Binary_Output_Encode_Property_APDU(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Valid_Instance(object_instance)) {
apdu_len = Binary_Value_Encode_Property_APDU(
&apdu[0],
apdu_len = Binary_Value_Encode_Property_APDU(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
case OBJECT_LIFE_SAFETY_POINT:
if (Life_Safety_Point_Valid_Instance(object_instance)) {
apdu_len = Life_Safety_Point_Encode_Property_APDU(
&apdu[0],
apdu_len = Life_Safety_Point_Encode_Property_APDU(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
case OBJECT_LOAD_CONTROL:
if (Load_Control_Valid_Instance(object_instance)) {
apdu_len = Load_Control_Encode_Property_APDU(
&apdu[0],
apdu_len = Load_Control_Encode_Property_APDU(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
case OBJECT_MULTI_STATE_OUTPUT:
if (Multistate_Output_Valid_Instance(object_instance)) {
apdu_len = Multistate_Output_Encode_Property_APDU(
&apdu[0],
apdu_len = Multistate_Output_Encode_Property_APDU(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
#if defined(BACFILE)
case OBJECT_FILE:
if (bacfile_valid_instance(object_instance)) {
apdu_len = bacfile_encode_property_apdu(
&apdu[0],
apdu_len = bacfile_encode_property_apdu(&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
property, array_index, error_class, error_code);
}
break;
#endif
@@ -190,9 +157,11 @@ int Encode_Property_APDU(
return apdu_len;
}
void handler_read_property(uint8_t * service_request,
void handler_read_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_READ_PROPERTY_DATA data;
int len = 0;
@@ -237,13 +206,10 @@ void handler_read_property(uint8_t * service_request,
/* assume that there is an error */
error = true;
len = Encode_Property_APDU(
&Temp_Buf[0],
len = Encode_Property_APDU(&Temp_Buf[0],
data.object_type,
data.object_instance,
data.object_property,
data.array_index,
&error_class, &error_code);
data.object_property, data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
@@ -253,8 +219,7 @@ void handler_read_property(uint8_t * service_request,
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, &data);
#if PRINT_ENABLED
fprintf(stderr,
"RP: Sending Ack!\n");
fprintf(stderr, "RP: Sending Ack!\n");
#endif
error = false;
}
@@ -276,7 +241,7 @@ void handler_read_property(uint8_t * service_request,
#endif
}
}
RP_ABORT:
RP_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+7 -5
View File
@@ -42,7 +42,8 @@
#include "txbuf.h"
/* for debugging... */
static void PrintReadPropertyData(BACNET_READ_PROPERTY_DATA * data)
static void PrintReadPropertyData(
BACNET_READ_PROPERTY_DATA * data)
{
BACNET_APPLICATION_DATA_VALUE value; /* for decode value data */
int len = 0;
@@ -95,17 +96,18 @@ static void PrintReadPropertyData(BACNET_READ_PROPERTY_DATA * data)
}
}
void handler_read_property_ack(uint8_t * service_request,
void handler_read_property_ack(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
{
int len = 0;
BACNET_READ_PROPERTY_DATA data;
(void) src;
(void) service_data; /* we could use these... */
len = rp_ack_decode_service_request(service_request,
service_len, &data);
len = rp_ack_decode_service_request(service_request, service_len, &data);
#if 0
fprintf(stderr, "Received Read-Property Ack!\n");
#endif
+143 -190
View File
@@ -49,25 +49,24 @@
#include "lsp.h"
#include "mso.h"
#if defined(BACFILE)
#include "bacfile.h"
#include "bacfile.h"
#endif
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
struct property_list_t
{
struct property_list_t {
const int *pList;
unsigned count;
};
struct special_property_list_t
{
struct special_property_list_t {
struct property_list_t Required;
struct property_list_t Optional;
struct property_list_t Proprietary;
};
static unsigned property_list_count(const int *pList)
static unsigned property_list_count(
const int *pList)
{
unsigned property_count = 0;
@@ -90,72 +89,62 @@ static void RPM_Property_List(
pPropertyList->Optional.pList = NULL;
pPropertyList->Proprietary.pList = NULL;
switch (object_type) {
case OBJECT_ANALOG_INPUT:
Analog_Input_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_ANALOG_OUTPUT:
Analog_Output_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_ANALOG_VALUE:
Analog_Value_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_BINARY_INPUT:
Binary_Input_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_BINARY_OUTPUT:
Binary_Output_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_BINARY_VALUE:
Binary_Value_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_LIFE_SAFETY_POINT:
Life_Safety_Point_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_LOAD_CONTROL:
Load_Control_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_MULTI_STATE_OUTPUT:
break;
case OBJECT_ANALOG_INPUT:
Analog_Input_Property_Lists(&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_ANALOG_OUTPUT:
Analog_Output_Property_Lists(&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_ANALOG_VALUE:
Analog_Value_Property_Lists(&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_BINARY_INPUT:
Binary_Input_Property_Lists(&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_BINARY_OUTPUT:
Binary_Output_Property_Lists(&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_BINARY_VALUE:
Binary_Value_Property_Lists(&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_LIFE_SAFETY_POINT:
Life_Safety_Point_Property_Lists(&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_LOAD_CONTROL:
Load_Control_Property_Lists(&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_MULTI_STATE_OUTPUT:
break;
#if defined(BACFILE)
case OBJECT_FILE:
BACfile_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_FILE:
BACfile_Property_Lists(&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
#endif
case OBJECT_DEVICE:
Device_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
default:
break;
case OBJECT_DEVICE:
Device_Property_Lists(&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
default:
break;
}
/* fill the count */
pPropertyList->Required.count =
@@ -173,7 +162,7 @@ static int RPM_Object_Property(
BACNET_PROPERTY_ID special_property,
unsigned index)
{
int property = -1; /* return value */
int property = -1; /* return value */
unsigned required, optional, proprietary;
required = pPropertyList->Required.count;
@@ -210,8 +199,7 @@ static unsigned RPM_Object_Property_Count(
if (special_property == PROP_ALL) {
count = pPropertyList->Required.count +
pPropertyList->Optional.count +
pPropertyList->Proprietary.count;
pPropertyList->Optional.count + pPropertyList->Proprietary.count;
} else if (special_property == PROP_REQUIRED) {
count = pPropertyList->Required.count;
} else if (special_property == PROP_OPTIONAL) {
@@ -222,14 +210,19 @@ static unsigned RPM_Object_Property_Count(
}
/* copy len bytes from src to offset of dest if there is enough space. */
int apdu_copy(uint8_t *dest, uint8_t *src, int offset, int len, int max)
int apdu_copy(
uint8_t * dest,
uint8_t * src,
int offset,
int len,
int max)
{
int i;
int copy_len = 0;
if (len <= (max-offset)) {
if (len <= (max - offset)) {
for (i = 0; i < len; i++) {
dest[offset+i] = src[i];
dest[offset + i] = src[i];
copy_len++;
}
}
@@ -239,7 +232,8 @@ int apdu_copy(uint8_t *dest, uint8_t *src, int offset, int len, int max)
/* Encode the RPM property returning the length of the encoding,
or 0 if there is no room to fit the encoding. */
int RPM_Encode_Property(uint8_t *apdu,
int RPM_Encode_Property(
uint8_t * apdu,
uint16_t offset,
uint16_t max_apdu,
BACNET_OBJECT_TYPE object_type,
@@ -252,35 +246,30 @@ int RPM_Encode_Property(uint8_t *apdu,
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
len = rpm_ack_encode_apdu_object_property(
&Temp_Buf[0],
object_property,
array_index);
len = rpm_ack_encode_apdu_object_property(&Temp_Buf[0],
object_property, array_index);
len = apdu_copy(&apdu[0], &Temp_Buf[0], offset, len, max_apdu);
if (!len)
return 0;
apdu_len += len;
len = Encode_Property_APDU(
&Temp_Buf[0],
len = Encode_Property_APDU(&Temp_Buf[0],
object_type,
object_instance,
object_property,
array_index,
&error_class, &error_code);
object_property, array_index, &error_class, &error_code);
if (len < 0) {
/* error was returned - encode that for the response */
len = rpm_ack_encode_apdu_object_property_error(
&Temp_Buf[0],
len = rpm_ack_encode_apdu_object_property_error(&Temp_Buf[0],
error_class, error_code);
len = apdu_copy(&apdu[0], &Temp_Buf[0], offset+apdu_len, len, max_apdu);
len =
apdu_copy(&apdu[0], &Temp_Buf[0], offset + apdu_len, len,
max_apdu);
if (!len)
return 0;
} else if ((offset+apdu_len+1+len+1) < max_apdu) {
} else if ((offset + apdu_len + 1 + len + 1) < max_apdu) {
/* enough room to fit the property value and tags */
len = rpm_ack_encode_apdu_object_property_value(
&apdu[offset+apdu_len],
&Temp_Buf[0],
len);
len =
rpm_ack_encode_apdu_object_property_value(&apdu[offset + apdu_len],
&Temp_Buf[0], len);
} else {
/* not enough room - abort! */
return 0;
@@ -311,16 +300,14 @@ void handler_read_property_multiple(
int32_t array_index = 0;
/* jps_debug - see if we are utilizing all the buffer */
/* memset(&Handler_Transmit_Buffer[0], 0xff, sizeof(Handler_Transmit_Buffer));*/
/* memset(&Handler_Transmit_Buffer[0], 0xff, sizeof(Handler_Transmit_Buffer)); */
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
npdu_len = npdu_encode_pdu(
&Handler_Transmit_Buffer[0],
npdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0],
src, &my_address, &npdu_data);
if (service_data->segmented_message) {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
apdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
#if PRINT_ENABLED
@@ -330,102 +317,82 @@ void handler_read_property_multiple(
}
/* decode apdu request & encode apdu reply
encode complex ack, invoke id, service choice */
apdu_len = rpm_ack_encode_apdu_init(
&Handler_Transmit_Buffer[npdu_len],
apdu_len = rpm_ack_encode_apdu_init(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id);
do
{
len = rpm_decode_object_id(
&service_request[decode_len],
service_len - decode_len,
&object_type, &object_instance);
do {
len = rpm_decode_object_id(&service_request[decode_len],
service_len - decode_len, &object_type, &object_instance);
/* end of object? */
if (len > 0) {
decode_len += len;
} else {
len = rpm_decode_object_end(
&service_request[decode_len],
len = rpm_decode_object_end(&service_request[decode_len],
service_len - decode_len);
if (len == 1) {
decode_len++;
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
copy_len = apdu_copy(
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
apdu_len, len,
sizeof(Handler_Transmit_Buffer));
copy_len =
apdu_copy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
apdu_len, len, sizeof(Handler_Transmit_Buffer));
if (!copy_len) {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
goto RPM_ABORT;
} else {
apdu_len += copy_len;
}
} else {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_OTHER, true);
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
goto RPM_ABORT;
}
break;
}
len = rpm_ack_encode_apdu_object_begin(
&Temp_Buf[0],
len = rpm_ack_encode_apdu_object_begin(&Temp_Buf[0],
object_type, object_instance);
copy_len = apdu_copy(
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
apdu_len, len,
sizeof(Handler_Transmit_Buffer));
copy_len = apdu_copy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
apdu_len, len, sizeof(Handler_Transmit_Buffer));
if (!copy_len) {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
apdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
goto RPM_ABORT;
} else {
apdu_len += copy_len;
}
/* do each property of this object of the RPM request */
do
{
len = rpm_decode_object_property(
&service_request[decode_len],
service_len - decode_len,
&object_property,
&array_index);
do {
len = rpm_decode_object_property(&service_request[decode_len],
service_len - decode_len, &object_property, &array_index);
/* end of property list? */
if (len > 0) {
decode_len += len;
} else {
len = rpm_decode_object_end(
&service_request[decode_len],
len = rpm_decode_object_end(&service_request[decode_len],
service_len - decode_len);
if (len == 1) {
decode_len++;
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
copy_len = apdu_copy(
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
apdu_len, len,
copy_len =
apdu_copy(&Handler_Transmit_Buffer[npdu_len],
&Temp_Buf[0], apdu_len, len,
sizeof(Handler_Transmit_Buffer));
if (!copy_len) {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer
[npdu_len], service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
goto RPM_ABORT;
} else {
apdu_len += copy_len;
}
} else {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_OTHER, true);
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
goto RPM_ABORT;
}
/* stop decoding properties */
@@ -434,8 +401,7 @@ void handler_read_property_multiple(
/* handle the special properties */
if ((object_property == PROP_ALL) ||
(object_property == PROP_REQUIRED) ||
(object_property == PROP_OPTIONAL))
{
(object_property == PROP_OPTIONAL)) {
struct special_property_list_t property_list;
unsigned property_count = 0;
unsigned index = 0;
@@ -443,63 +409,50 @@ void handler_read_property_multiple(
special_object_property = object_property;
RPM_Property_List(object_type, &property_list);
property_count = RPM_Object_Property_Count(
&property_list,
property_count = RPM_Object_Property_Count(&property_list,
special_object_property);
for (index = 0; index < property_count; index++)
{
object_property = RPM_Object_Property(
&property_list,
special_object_property,
index);
len = RPM_Encode_Property(
&Handler_Transmit_Buffer[0],
for (index = 0; index < property_count; index++) {
object_property = RPM_Object_Property(&property_list,
special_object_property, index);
len = RPM_Encode_Property(&Handler_Transmit_Buffer[0],
npdu_len + apdu_len,
sizeof(Handler_Transmit_Buffer),
object_type,
object_instance,
object_property,
array_index);
object_instance, object_property, array_index);
if (len > 0) {
apdu_len += len;
} else {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
goto RPM_ABORT;
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer
[npdu_len], service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
goto RPM_ABORT;
}
}
} else {
/* handle an individual property */
len = RPM_Encode_Property(
&Handler_Transmit_Buffer[0],
len = RPM_Encode_Property(&Handler_Transmit_Buffer[0],
npdu_len + apdu_len,
sizeof(Handler_Transmit_Buffer),
object_type,
object_instance,
object_property,
array_index);
object_instance, object_property, array_index);
if (len > 0) {
apdu_len += len;
} else {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
goto RPM_ABORT;
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
goto RPM_ABORT;
}
}
} while(1);
} while (1);
if (decode_len >= service_len) {
break;
}
} while(1);
RPM_ABORT:
} while (1);
RPM_ABORT:
pdu_len = apdu_len + npdu_len;
bytes_sent = datalink_send_pdu(
src,
&npdu_data,
&Handler_Transmit_Buffer[0],
pdu_len);
bytes_sent = datalink_send_pdu(src,
&npdu_data, &Handler_Transmit_Buffer[0], pdu_len);
}
+11 -6
View File
@@ -32,7 +32,9 @@
#include "timesync.h"
#if PRINT_ENABLED
static void show_bacnet_date_time(BACNET_DATE * bdate, BACNET_TIME * btime)
static void show_bacnet_date_time(
BACNET_DATE * bdate,
BACNET_TIME * btime)
{
/* show the date received */
fprintf(stderr, "%u", (unsigned) bdate->year);
@@ -47,8 +49,10 @@ static void show_bacnet_date_time(BACNET_DATE * bdate, BACNET_TIME * btime)
}
#endif
void handler_timesync(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
void handler_timesync(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
BACNET_DATE bdate;
@@ -67,8 +71,10 @@ void handler_timesync(uint8_t * service_request,
return;
}
void handler_timesync_utc(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
void handler_timesync_utc(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
BACNET_DATE bdate;
@@ -86,4 +92,3 @@ void handler_timesync_utc(uint8_t * service_request,
return;
}
+7 -8
View File
@@ -35,8 +35,10 @@
#include "device.h"
#include "client.h"
void handler_who_has(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
void handler_who_has(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
BACNET_WHO_HAS_DATA data;
@@ -47,15 +49,12 @@ void handler_who_has(uint8_t * service_request,
bool found = false;
(void) src;
len = whohas_decode_service_request(service_request,
service_len, &data);
len = whohas_decode_service_request(service_request, service_len, &data);
if (len > 0) {
if ((data.low_limit == -1) || (data.high_limit == -1))
directed_to_me = true;
else if ((Device_Object_Instance_Number() >=
(uint32_t) data.low_limit)
&& (Device_Object_Instance_Number() <=
(uint32_t) data.high_limit))
else if ((Device_Object_Instance_Number() >= (uint32_t) data.low_limit)
&& (Device_Object_Instance_Number() <= (uint32_t) data.high_limit))
directed_to_me = true;
if (directed_to_me) {
/* do we have such an object? If so, send an I-Have.
+4 -2
View File
@@ -37,8 +37,10 @@
#include "client.h"
#include "txbuf.h"
void handler_who_is(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
void handler_who_is(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
int32_t low_limit = 0;
+204 -231
View File
@@ -47,12 +47,14 @@
#include "lsp.h"
#include "mso.h"
#if defined(BACFILE)
#include "bacfile.h"
#include "bacfile.h"
#endif
void handler_write_property(uint8_t * service_request,
void handler_write_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_WRITE_PROPERTY_DATA wp_data;
int len = 0;
@@ -79,9 +81,8 @@ void handler_write_property(uint8_t * service_request,
fprintf(stderr, "WP: Segmented message. Sending Abort!\n");
#endif
goto WP_ABORT;
} /* decode the service request only */
len = wp_decode_service_request(service_request,
service_len, &wp_data);
} /* decode the service request only */
len = wp_decode_service_request(service_request, service_len, &wp_data);
#if PRINT_ENABLED
if (len > 0)
fprintf(stderr, "WP: type=%u instance=%u property=%u index=%d\n",
@@ -99,232 +100,204 @@ void handler_write_property(uint8_t * service_request,
fprintf(stderr, "WP: Bad Encoding. Sending Abort!\n");
#endif
goto WP_ABORT;
}
switch (wp_data.object_type) {
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Simple Ack for Device!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Error for Device!\n");
#endif
}
break;
case OBJECT_ANALOG_INPUT:
case OBJECT_BINARY_INPUT:
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error!\n");
#endif
break;
case OBJECT_BINARY_OUTPUT:
if (Binary_Output_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Simple Ack for BO!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for BO!\n");
#endif
}
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Simple Ack for BV!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for BV!\n");
#endif
}
break;
case OBJECT_ANALOG_OUTPUT:
if (Analog_Output_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Simple Ack for AO!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for AO!\n");
#endif
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Simple Ack for AV!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for AV!\n");
#endif
}
break;
case OBJECT_LIFE_SAFETY_POINT:
if (Life_Safety_Point_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Simple Ack for LSP!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for LSP!\n");
#endif
}
break;
case OBJECT_LOAD_CONTROL:
if (Load_Control_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Simple Ack for Load Control!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Write Access Error for Load Control!\n");
#endif
}
break;
case OBJECT_MULTI_STATE_OUTPUT:
if (Multistate_Output_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Write Property Simple Ack for MSO!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for MSO!\n");
#endif
}
break;
#if defined(BACFILE)
case OBJECT_FILE:
if (bacfile_write_property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Simple Ack for File!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for File!\n");
#endif
}
break;
#endif /* BACFILE */
default:
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Unknown Object Error!\n");
#endif
break;
}
WP_ABORT:
switch (wp_data.object_type) {
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Simple Ack for Device!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Error for Device!\n");
#endif
}
break;
case OBJECT_ANALOG_INPUT:
case OBJECT_BINARY_INPUT:
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error!\n");
#endif
break;
case OBJECT_BINARY_OUTPUT:
if (Binary_Output_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Simple Ack for BO!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for BO!\n");
#endif
}
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Simple Ack for BV!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for BV!\n");
#endif
}
break;
case OBJECT_ANALOG_OUTPUT:
if (Analog_Output_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Simple Ack for AO!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for AO!\n");
#endif
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Simple Ack for AV!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for AV!\n");
#endif
}
break;
case OBJECT_LIFE_SAFETY_POINT:
if (Life_Safety_Point_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Simple Ack for LSP!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for LSP!\n");
#endif
}
break;
case OBJECT_LOAD_CONTROL:
if (Load_Control_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Simple Ack for Load Control!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Write Access Error for Load Control!\n");
#endif
}
break;
case OBJECT_MULTI_STATE_OUTPUT:
if (Multistate_Output_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"WP: Sending Write Property Simple Ack for MSO!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for MSO!\n");
#endif
}
break;
#if defined(BACFILE)
case OBJECT_FILE:
if (bacfile_write_property(&wp_data, &error_class, &error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Simple Ack for File!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Write Access Error for File!\n");
#endif
}
break;
#endif /* BACFILE */
default:
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Unknown Object Error!\n");
#endif
break;
}
WP_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+4 -2
View File
@@ -34,9 +34,11 @@
#include "npdu.h"
#include "reject.h"
void handler_unrecognized_service(uint8_t * service_request,
void handler_unrecognized_service(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
int len = 0;
int pdu_len = 0;
+4 -2
View File
@@ -42,9 +42,11 @@
#include "handlers.h"
#include "txbuf.h"
uint8_t Send_Atomic_Read_File_Stream(uint32_t device_id,
uint8_t Send_Atomic_Read_File_Stream(
uint32_t device_id,
uint32_t file_instance,
int fileStartPosition, unsigned requestedOctetCount)
int fileStartPosition,
unsigned requestedOctetCount)
{
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
+6 -6
View File
@@ -42,9 +42,11 @@
#include "handlers.h"
#include "txbuf.h"
uint8_t Send_Atomic_Write_File_Stream(uint32_t device_id,
uint8_t Send_Atomic_Write_File_Stream(
uint32_t device_id,
uint32_t file_instance,
int fileStartPosition, BACNET_OCTET_STRING * fileData)
int fileStartPosition,
BACNET_OCTET_STRING * fileData)
{
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
@@ -76,8 +78,7 @@ uint8_t Send_Atomic_Write_File_Stream(uint32_t device_id,
if (status) {
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, true,
MESSAGE_PRIORITY_NORMAL);
npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest,
&my_address, &npdu_data);
@@ -116,8 +117,7 @@ uint8_t Send_Atomic_Write_File_Stream(uint32_t device_id,
invoke_id = 0;
#if PRINT_ENABLED
fprintf(stderr, "Failed to Send AtomicWriteFile Request "
"(payload [%d] exceeds octet string capacity)!\n",
pdu_len);
"(payload [%d] exceeds octet string capacity)!\n", pdu_len);
#endif
}
}
+6 -3
View File
@@ -42,9 +42,12 @@
#include "handlers.h"
#include "txbuf.h"
uint8_t Send_Device_Communication_Control_Request(uint32_t device_id, uint16_t timeDuration, /* 0=optional */
BACNET_COMMUNICATION_ENABLE_DISABLE state, char *password)
{ /* NULL=optional */
uint8_t Send_Device_Communication_Control_Request(
uint32_t device_id,
uint16_t timeDuration, /* 0=optional */
BACNET_COMMUNICATION_ENABLE_DISABLE state,
char *password)
{ /* NULL=optional */
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
+4 -2
View File
@@ -44,9 +44,11 @@
#include "txbuf.h"
/* find a specific device, or use -1 for limit if you want unlimited */
void Send_I_Have(uint32_t device_id,
void Send_I_Have(
uint32_t device_id,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance, char *object_name)
uint32_t object_instance,
char *object_name)
{
int len = 0;
int pdu_len = 0;
+4 -2
View File
@@ -42,8 +42,10 @@
#include "handlers.h"
#include "txbuf.h"
uint8_t Send_Reinitialize_Device_Request(uint32_t device_id,
BACNET_REINITIALIZED_STATE state, char *password)
uint8_t Send_Reinitialize_Device_Request(
uint32_t device_id,
BACNET_REINITIALIZED_STATE state,
char *password)
{
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
+5 -4
View File
@@ -44,10 +44,12 @@
#include "txbuf.h"
/* returns invoke id of 0 if device is not bound or no tsm available */
uint8_t Send_Read_Property_Request(uint32_t device_id, /* destination device */
uint8_t Send_Read_Property_Request(
uint32_t device_id, /* destination device */
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID object_property, int32_t array_index)
BACNET_PROPERTY_ID object_property,
int32_t array_index)
{
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
@@ -89,8 +91,7 @@ uint8_t Send_Read_Property_Request(uint32_t device_id, /* destination device */
max_apdu in the address binding table. */
if ((unsigned) pdu_len < max_apdu) {
tsm_set_confirmed_unsegmented_transaction(invoke_id, &dest,
&npdu_data, &Handler_Transmit_Buffer[0],
(uint16_t) pdu_len);
&npdu_data, &Handler_Transmit_Buffer[0], (uint16_t) pdu_len);
bytes_sent =
datalink_send_pdu(&dest, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+6 -2
View File
@@ -42,7 +42,9 @@
#include "handlers.h"
#include "txbuf.h"
void Send_TimeSync(BACNET_DATE * bdate, BACNET_TIME * btime)
void Send_TimeSync(
BACNET_DATE * bdate,
BACNET_TIME * btime)
{
int len = 0;
int pdu_len = 0;
@@ -74,7 +76,9 @@ void Send_TimeSync(BACNET_DATE * bdate, BACNET_TIME * btime)
#endif
}
void Send_TimeSyncUTC(BACNET_DATE * bdate, BACNET_TIME * btime)
void Send_TimeSyncUTC(
BACNET_DATE * bdate,
BACNET_TIME * btime)
{
int pdu_len = 0;
BACNET_ADDRESS dest;
+8 -4
View File
@@ -43,8 +43,10 @@
#include "txbuf.h"
/* find a specific device, or use -1 for limit if you want unlimited */
void Send_WhoHas_Name(int32_t low_limit,
int32_t high_limit, char *object_name)
void Send_WhoHas_Name(
int32_t low_limit,
int32_t high_limit,
char *object_name)
{
int len = 0;
int pdu_len = 0;
@@ -80,9 +82,11 @@ void Send_WhoHas_Name(int32_t low_limit,
}
/* find a specific device, or use -1 for limit if you want unlimited */
void Send_WhoHas_Object(int32_t low_limit,
void Send_WhoHas_Object(
int32_t low_limit,
int32_t high_limit,
BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance)
{
int len = 0;
int pdu_len = 0;
+3 -1
View File
@@ -44,7 +44,9 @@
#include "txbuf.h"
/* find a specific device, or use -1 for limit if you want unlimited */
void Send_WhoIs(int32_t low_limit, int32_t high_limit)
void Send_WhoIs(
int32_t low_limit,
int32_t high_limit)
{
int len = 0;
int pdu_len = 0;
+14 -10
View File
@@ -44,12 +44,15 @@
#include "txbuf.h"
/* returns the invoke ID for confirmed request, or zero on failure */
uint8_t Send_Write_Property_Request_Data(uint32_t device_id,
uint8_t Send_Write_Property_Request_Data(
uint32_t device_id,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID object_property,
uint8_t * application_data,
int application_data_len, uint8_t priority, int32_t array_index)
int application_data_len,
uint8_t priority,
int32_t array_index)
{
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
@@ -95,8 +98,7 @@ uint8_t Send_Write_Property_Request_Data(uint32_t device_id,
max_apdu in the address binding table. */
if ((unsigned) pdu_len < max_apdu) {
tsm_set_confirmed_unsegmented_transaction(invoke_id, &dest,
&npdu_data, &Handler_Transmit_Buffer[0],
(uint16_t) pdu_len);
&npdu_data, &Handler_Transmit_Buffer[0], (uint16_t) pdu_len);
bytes_sent =
datalink_send_pdu(&dest, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
@@ -119,12 +121,14 @@ uint8_t Send_Write_Property_Request_Data(uint32_t device_id,
return invoke_id;
}
uint8_t Send_Write_Property_Request(uint32_t device_id,
uint8_t Send_Write_Property_Request(
uint32_t device_id,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID object_property,
BACNET_APPLICATION_DATA_VALUE * object_value,
uint8_t priority, int32_t array_index)
uint8_t priority,
int32_t array_index)
{
uint8_t application_data[MAX_APDU] = { 0 };
int apdu_len = 0, len = 0;
@@ -133,11 +137,11 @@ uint8_t Send_Write_Property_Request(uint32_t device_id,
#if PRINT_ENABLED_DEBUG
fprintf(stderr, "WriteProperty service: "
"%s tag=%d\n",
(object_value->context_specific?"context":"application"),
(int)(object_value->context_specific?object_value->context_tag:object_value->tag) );
(object_value->context_specific ? "context" : "application"),
(int) (object_value->context_specific ? object_value->
context_tag : object_value->tag));
#endif
len = bacapp_encode_data(&application_data[apdu_len],
object_value);
len = bacapp_encode_data(&application_data[apdu_len], object_value);
if ((len + apdu_len) < MAX_APDU) {
apdu_len += len;
} else {
+76 -68
View File
@@ -31,13 +31,12 @@
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#define MAX_ANALOG_INPUTS 7
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Analog_Input_Properties_Required[] =
{
static const int Analog_Input_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
@@ -49,14 +48,12 @@ static const int Analog_Input_Properties_Required[] =
-1
};
static const int Analog_Input_Properties_Optional[] =
{
static const int Analog_Input_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Analog_Input_Properties_Proprietary[] =
{
static const int Analog_Input_Properties_Proprietary[] = {
9997,
9998,
9999,
@@ -81,7 +78,8 @@ void Analog_Input_Property_Lists(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Analog_Input_Valid_Instance(uint32_t object_instance)
bool Analog_Input_Valid_Instance(
uint32_t object_instance)
{
if (object_instance < MAX_ANALOG_INPUTS)
return true;
@@ -91,7 +89,8 @@ bool Analog_Input_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Analog_Input_Count(void)
unsigned Analog_Input_Count(
void)
{
return MAX_ANALOG_INPUTS;
}
@@ -99,12 +98,14 @@ unsigned Analog_Input_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Analog_Input_Index_To_Instance(unsigned index)
uint32_t Analog_Input_Index_To_Instance(
unsigned index)
{
return index;
}
char *Analog_Input_Name(uint32_t object_instance)
char *Analog_Input_Name(
uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
@@ -118,67 +119,73 @@ char *Analog_Input_Name(uint32_t object_instance)
/* return apdu length, or -1 on error */
/* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
int Analog_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)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
float value = 3.14159F;
(void) array_index;
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_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_ANALOG_INPUT);
break;
case PROP_PRESENT_VALUE:
apdu_len = encode_application_real(&apdu[0], value);
break;
case PROP_STATUS_FLAGS:
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:
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_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
case 9997:
apdu_len = encode_application_real(&apdu[0], (float) 90.510);
break;
case 9998:
apdu_len = encode_application_unsigned(&apdu[0], 90);
break;
/* test case for signed encoding-decoding negative value correctly */
case 9999:
apdu_len = encode_application_signed(&apdu[0], -200);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_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_ANALOG_INPUT);
break;
case PROP_PRESENT_VALUE:
apdu_len = encode_application_real(&apdu[0], value);
break;
case PROP_STATUS_FLAGS:
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:
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_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
case 9997:
apdu_len = encode_application_real(&apdu[0], (float) 90.510);
break;
case 9998:
apdu_len = encode_application_unsigned(&apdu[0], 90);
break;
/* test case for signed encoding-decoding negative value correctly */
case 9999:
apdu_len = encode_application_signed(&apdu[0], -200);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
@@ -189,7 +196,8 @@ int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
#include <string.h>
#include "ctest.h"
void testAnalogInput(Test * pTest)
void testAnalogInput(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -205,8 +213,7 @@ void testAnalogInput(Test * pTest)
/* FIXME: we should do a lot more testing here... */
len = Analog_Input_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len >= 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -219,7 +226,8 @@ void testAnalogInput(Test * pTest)
}
#ifdef TEST_ANALOG_INPUT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -236,5 +244,5 @@ int main(void)
return 0;
}
#endif /* TEST_ANALOG_INPUT */
#endif /* TEST */
#endif /* TEST_ANALOG_INPUT */
#endif /* TEST */
+184 -166
View File
@@ -32,7 +32,7 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_ANALOG_OUTPUTS 4
@@ -47,8 +47,7 @@
/* Here is our Priority Array. They are supposed to be Real, but */
/* we don't have that kind of memory, so we will use a single byte */
/* and load a Real for returning the value when asked. */
static uint8_t
Analog_Output_Level[MAX_ANALOG_OUTPUTS][BACNET_MAX_PRIORITY];
static uint8_t Analog_Output_Level[MAX_ANALOG_OUTPUTS][BACNET_MAX_PRIORITY];
/* Writable out-of-service allows others to play with our Present Value */
/* without changing the physical output */
static bool Analog_Output_Out_Of_Service[MAX_ANALOG_OUTPUTS];
@@ -57,8 +56,7 @@ static bool Analog_Output_Out_Of_Service[MAX_ANALOG_OUTPUTS];
static bool Analog_Output_Initialized = false;
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Analog_Output_Properties_Required[] =
{
static const int Analog_Output_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
@@ -72,14 +70,12 @@ static const int Analog_Output_Properties_Required[] =
-1
};
static const int Analog_Output_Properties_Optional[] =
{
static const int Analog_Output_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Analog_Output_Properties_Proprietary[] =
{
static const int Analog_Output_Properties_Proprietary[] = {
-1
};
@@ -98,7 +94,8 @@ void Analog_Output_Property_Lists(
return;
}
void Analog_Output_Init(void)
void Analog_Output_Init(
void)
{
unsigned i, j;
@@ -119,7 +116,8 @@ void Analog_Output_Init(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Analog_Output_Valid_Instance(uint32_t object_instance)
bool Analog_Output_Valid_Instance(
uint32_t object_instance)
{
Analog_Output_Init();
if (object_instance < MAX_ANALOG_OUTPUTS)
@@ -130,7 +128,8 @@ bool Analog_Output_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Analog_Output_Count(void)
unsigned Analog_Output_Count(
void)
{
Analog_Output_Init();
return MAX_ANALOG_OUTPUTS;
@@ -139,7 +138,8 @@ unsigned Analog_Output_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Analog_Output_Index_To_Instance(unsigned index)
uint32_t Analog_Output_Index_To_Instance(
unsigned index)
{
Analog_Output_Init();
return index;
@@ -148,7 +148,8 @@ uint32_t Analog_Output_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Analog_Output_Instance_To_Index(uint32_t object_instance)
unsigned Analog_Output_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_ANALOG_OUTPUTS;
@@ -159,7 +160,8 @@ unsigned Analog_Output_Instance_To_Index(uint32_t object_instance)
return index;
}
float Analog_Output_Present_Value(uint32_t object_instance)
float Analog_Output_Present_Value(
uint32_t object_instance)
{
float value = AO_RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -179,10 +181,11 @@ float Analog_Output_Present_Value(uint32_t object_instance)
return value;
}
unsigned Analog_Output_Present_Value_Priority(uint32_t object_instance)
unsigned Analog_Output_Present_Value_Priority(
uint32_t object_instance)
{
unsigned index = 0; /* instance to index conversion */
unsigned i = 0; /* loop counter */
unsigned index = 0; /* instance to index conversion */
unsigned i = 0; /* loop counter */
unsigned priority = 0; /* return value */
Analog_Output_Init();
@@ -199,8 +202,10 @@ unsigned Analog_Output_Present_Value_Priority(uint32_t object_instance)
return priority;
}
bool Analog_Output_Present_Value_Set(uint32_t object_instance,
float value, unsigned priority)
bool Analog_Output_Present_Value_Set(
uint32_t object_instance,
float value,
unsigned priority)
{
unsigned index = 0;
bool status = false;
@@ -210,7 +215,7 @@ bool Analog_Output_Present_Value_Set(uint32_t object_instance,
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value >= 0.0) && (value <= 100.0)) {
Analog_Output_Level[index][priority-1] = (uint8_t) value;
Analog_Output_Level[index][priority - 1] = (uint8_t) value;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
@@ -224,7 +229,8 @@ bool Analog_Output_Present_Value_Set(uint32_t object_instance,
return status;
}
bool Analog_Output_Present_Value_Relinquish(uint32_t object_instance,
bool Analog_Output_Present_Value_Relinquish(
uint32_t object_instance,
unsigned priority)
{
unsigned index = 0;
@@ -234,7 +240,7 @@ bool Analog_Output_Present_Value_Relinquish(uint32_t object_instance,
if (index < MAX_ANALOG_OUTPUTS) {
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ )) {
Analog_Output_Level[index][priority-1] = AO_LEVEL_NULL;
Analog_Output_Level[index][priority - 1] = AO_LEVEL_NULL;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
@@ -249,7 +255,8 @@ bool Analog_Output_Present_Value_Relinquish(uint32_t object_instance,
}
/* note: the object name must be unique within this device */
char *Analog_Output_Name(uint32_t object_instance)
char *Analog_Output_Name(
uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
@@ -262,14 +269,16 @@ char *Analog_Output_Name(uint32_t object_instance)
}
/* return apdu len, or -1 on error */
int Analog_Output_Encode_Property_APDU(uint8_t * apdu,
int Analog_Output_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)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int len = 0;
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
float real_value = (float) 1.414;
@@ -279,107 +288,115 @@ int Analog_Output_Encode_Property_APDU(uint8_t * apdu,
Analog_Output_Init();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_OUTPUT,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Output_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_ANALOG_OUTPUT);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Output_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_STATUS_FLAGS:
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:
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index = Analog_Output_Instance_To_Index(object_instance);
state = Analog_Output_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index =
Analog_Output_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Analog_Output_Level[object_index][i] == AO_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Analog_Output_Level[object_index][i];
len = encode_application_real(&apdu[apdu_len], real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index =
Analog_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Analog_Output_Level[object_index][array_index - 1] ==
AO_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Analog_Output_Level[object_index][array_index - 1];
apdu_len = encode_application_real(&apdu[0], real_value);
encode_application_object_id(&apdu[0], OBJECT_ANALOG_OUTPUT,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Output_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_ANALOG_OUTPUT);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Output_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_STATUS_FLAGS:
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:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index = Analog_Output_Instance_To_Index(object_instance);
state = Analog_Output_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index =
Analog_Output_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Analog_Output_Level[object_index][i] == AO_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Analog_Output_Level[object_index][i];
len =
encode_application_real(&apdu[apdu_len],
real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
object_index =
Analog_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Analog_Output_Level[object_index][array_index - 1] ==
AO_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Analog_Output_Level[object_index][array_index - 1];
apdu_len =
encode_application_real(&apdu[0], real_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
}
break;
case PROP_RELINQUISH_DEFAULT:
real_value = AO_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
break;
case PROP_RELINQUISH_DEFAULT:
real_value = AO_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Analog_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Analog_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -399,56 +416,56 @@ bool Analog_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
status =
Analog_Output_Present_Value_Set(wp_data->object_instance,
value.type.Real, wp_data->priority);
if (wp_data->priority == 6) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
status =
Analog_Output_Present_Value_Set(wp_data->object_instance,
value.type.Real, wp_data->priority);
if (wp_data->priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = AO_LEVEL_NULL;
object_index =
Analog_Output_Instance_To_Index(wp_data->object_instance);
status =
Analog_Output_Present_Value_Relinquish(wp_data->
object_instance, wp_data->priority);
if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = AO_LEVEL_NULL;
object_index =
Analog_Output_Instance_To_Index(wp_data->object_instance);
status =
Analog_Output_Present_Value_Relinquish(wp_data->
object_instance, wp_data->priority);
if (!status) {
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Analog_Output_Instance_To_Index(wp_data->object_instance);
Analog_Output_Out_Of_Service[object_index] =
value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Analog_Output_Instance_To_Index(wp_data->object_instance);
Analog_Output_Out_Of_Service[object_index] =
value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -460,7 +477,8 @@ bool Analog_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
#include <string.h>
#include "ctest.h"
void testAnalogOutput(Test * pTest)
void testAnalogOutput(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -475,8 +493,7 @@ void testAnalogOutput(Test * pTest)
len = Analog_Output_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -489,7 +506,8 @@ void testAnalogOutput(Test * pTest)
}
#ifdef TEST_ANALOG_OUTPUT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -506,5 +524,5 @@ int main(void)
return 0;
}
#endif /* TEST_ANALOG_INPUT */
#endif /* TEST */
#endif /* TEST_ANALOG_INPUT */
#endif /* TEST */
+186 -170
View File
@@ -32,7 +32,7 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_ANALOG_VALUES 4
@@ -56,8 +56,7 @@ static bool Analog_Value_Out_Of_Service[MAX_ANALOG_VALUES];
static bool Analog_Value_Initialized = false;
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Analog_Value_Properties_Required[] =
{
static const int Analog_Value_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
@@ -69,16 +68,14 @@ static const int Analog_Value_Properties_Required[] =
-1
};
static const int Analog_Value_Properties_Optional[] =
{
static const int Analog_Value_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
static const int Analog_Value_Properties_Proprietary[] =
{
static const int Analog_Value_Properties_Proprietary[] = {
-1
};
@@ -97,7 +94,8 @@ void Analog_Value_Property_Lists(
return;
}
void Analog_Value_Init(void)
void Analog_Value_Init(
void)
{
unsigned i, j;
@@ -118,7 +116,8 @@ void Analog_Value_Init(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Analog_Value_Valid_Instance(uint32_t object_instance)
bool Analog_Value_Valid_Instance(
uint32_t object_instance)
{
Analog_Value_Init();
if (object_instance < MAX_ANALOG_VALUES)
@@ -129,7 +128,8 @@ bool Analog_Value_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Analog_Value_Count(void)
unsigned Analog_Value_Count(
void)
{
Analog_Value_Init();
return MAX_ANALOG_VALUES;
@@ -138,7 +138,8 @@ unsigned Analog_Value_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Analog_Value_Index_To_Instance(unsigned index)
uint32_t Analog_Value_Index_To_Instance(
unsigned index)
{
Analog_Value_Init();
return index;
@@ -147,7 +148,8 @@ uint32_t Analog_Value_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
unsigned Analog_Value_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_ANALOG_VALUES;
@@ -158,7 +160,8 @@ unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
return index;
}
static float Analog_Value_Present_Value(uint32_t object_instance)
static float Analog_Value_Present_Value(
uint32_t object_instance)
{
float value = ANALOG_RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -179,7 +182,8 @@ static float Analog_Value_Present_Value(uint32_t object_instance)
}
/* note: the object name must be unique within this device */
char *Analog_Value_Name(uint32_t object_instance)
char *Analog_Value_Name(
uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
@@ -192,14 +196,16 @@ char *Analog_Value_Name(uint32_t object_instance)
}
/* return apdu len, or -1 on error */
int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
int Analog_Value_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)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int len = 0;
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
float real_value = (float) 1.414;
@@ -209,106 +215,115 @@ int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
Analog_Value_Init();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Value_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_ANALOG_VALUE);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Value_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_STATUS_FLAGS:
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:
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index = Analog_Value_Instance_To_Index(object_instance);
state = Analog_Value_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Value_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_ANALOG_VALUE);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Value_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_STATUS_FLAGS:
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:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index = Analog_Value_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Analog_Value_Level[object_index][i] ==
ANALOG_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Analog_Value_Level[object_index][i];
len = encode_application_real(&apdu[apdu_len], real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index = Analog_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Analog_Value_Level[object_index][array_index - 1] ==
ANALOG_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Analog_Value_Level[object_index][array_index - 1];
apdu_len = encode_application_real(&apdu[0], real_value);
state = Analog_Value_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index = Analog_Value_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Analog_Value_Level[object_index][i] ==
ANALOG_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Analog_Value_Level[object_index][i];
len =
encode_application_real(&apdu[apdu_len],
real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
object_index = Analog_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Analog_Value_Level[object_index][array_index - 1] ==
ANALOG_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Analog_Value_Level[object_index][array_index - 1];
apdu_len =
encode_application_real(&apdu[0], real_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
}
break;
case PROP_RELINQUISH_DEFAULT:
real_value = ANALOG_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
break;
case PROP_RELINQUISH_DEFAULT:
real_value = ANALOG_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Analog_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -329,76 +344,76 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
priority = wp_data->priority;
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value.type.Real >= 0.0) && (value.type.Real <= 100.0)) {
level = (uint8_t) value.type.Real;
object_index =
Analog_Value_Instance_To_Index(wp_data->
object_instance);
priority--;
Analog_Value_Level[object_index][priority] = level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else if (priority == 6) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
priority = wp_data->priority;
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value.type.Real >= 0.0) && (value.type.Real <= 100.0)) {
level = (uint8_t) value.type.Real;
object_index =
Analog_Value_Instance_To_Index(wp_data->
object_instance);
priority--;
Analog_Value_Level[object_index][priority] = level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else if (priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = ANALOG_LEVEL_NULL;
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Analog_Value_Level[object_index][priority] = level;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = ANALOG_LEVEL_NULL;
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Analog_Value_Level[object_index][priority] = level;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
Analog_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
Analog_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -410,7 +425,8 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
#include <string.h>
#include "ctest.h"
void testAnalog_Value(Test * pTest)
void testAnalog_Value(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -425,8 +441,7 @@ void testAnalog_Value(Test * pTest)
len = Analog_Value_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -439,7 +454,8 @@ void testAnalog_Value(Test * pTest)
}
#ifdef TEST_ANALOG_VALUE
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -456,5 +472,5 @@ int main(void)
return 0;
}
#endif /* TEST_ANALOG_VALUE */
#endif /* TEST */
#endif /* TEST_ANALOG_VALUE */
#endif /* TEST */
+137 -123
View File
@@ -49,12 +49,11 @@ static BACNET_FILE_LISTING BACnet_File_Listing[] = {
{0, "temp_0.txt"},
{1, "temp_1.txt"},
{2, "temp_2.txt"},
{0, NULL} /* last file indication */
{0, NULL} /* last file indication */
};
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int bacfile_Properties_Required[] =
{
static const int bacfile_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
@@ -67,14 +66,12 @@ static const int bacfile_Properties_Required[] =
-1
};
static const int bacfile_Properties_Optional[] =
{
static const int bacfile_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int bacfile_Properties_Proprietary[] =
{
static const int bacfile_Properties_Proprietary[] = {
-1
};
@@ -94,7 +91,8 @@ void BACfile_Property_Lists(
}
char *bacfile_name(uint32_t instance)
char *bacfile_name(
uint32_t instance)
{
uint32_t index = 0;
char *filename = NULL;
@@ -111,12 +109,14 @@ char *bacfile_name(uint32_t instance)
return filename;
}
bool bacfile_valid_instance(uint32_t object_instance)
bool bacfile_valid_instance(
uint32_t object_instance)
{
return bacfile_name(object_instance) ? true : false;
}
uint32_t bacfile_count(void)
uint32_t bacfile_count(
void)
{
uint32_t index = 0;
@@ -128,7 +128,8 @@ uint32_t bacfile_count(void)
return index;
}
uint32_t bacfile_index_to_instance(unsigned find_index)
uint32_t bacfile_index_to_instance(
unsigned find_index)
{
uint32_t instance = BACNET_MAX_INSTANCE + 1;
uint32_t index = 0;
@@ -145,7 +146,8 @@ uint32_t bacfile_index_to_instance(unsigned find_index)
return instance;
}
static long fsize(FILE * pFile)
static long fsize(
FILE * pFile)
{
long size = 0;
long origin = 0;
@@ -159,7 +161,8 @@ static long fsize(FILE * pFile)
return (size);
}
static unsigned bacfile_file_size(uint32_t object_instance)
static unsigned bacfile_file_size(
uint32_t object_instance)
{
char *pFilename = NULL;
FILE *pFile = NULL;
@@ -178,13 +181,15 @@ static unsigned bacfile_file_size(uint32_t object_instance)
}
/* return the number of bytes used, or -1 on error */
int bacfile_encode_property_apdu(uint8_t * apdu,
int bacfile_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)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
char text_string[32] = { "" };
BACNET_CHARACTER_STRING char_string;
BACNET_DATE bdate;
@@ -192,76 +197,82 @@ int bacfile_encode_property_apdu(uint8_t * apdu,
(void) array_index;
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0],
OBJECT_FILE, object_instance);
break;
case PROP_OBJECT_NAME:
sprintf(text_string, "FILE %d", object_instance);
characterstring_init_ansi(&char_string, text_string);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_FILE);
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
bacfile_name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_FILE_TYPE:
characterstring_init_ansi(&char_string, "TEXT");
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_FILE_SIZE:
apdu_len = encode_application_unsigned(&apdu[0],
bacfile_file_size(object_instance));
break;
case PROP_MODIFICATION_DATE:
/* FIXME: get the actual value instead of April Fool's Day */
bdate.year = 2006; /* AD */
bdate.month = 4; /* 1=Jan */
bdate.day = 1; /* 1..31 */
bdate.wday = 6; /* 1=Monday */
apdu_len = encode_application_date(&apdu[0], &bdate);
/* FIXME: get the actual value */
btime.hour = 7;
btime.min = 0;
btime.sec = 3;
btime.hundredths = 1;
apdu_len += encode_application_time(&apdu[apdu_len], &btime);
break;
case PROP_ARCHIVE:
/* 12.13.8 Archive
This property, of type BOOLEAN, indicates whether the File
object has been saved for historical or backup purposes. This
property shall be logical TRUE only if no changes have been
made to the file data by internal processes or through File
Access Services since the last time the object was archived.
*/
/* FIXME: get the actual value: note it may be inverse... */
apdu_len = encode_application_boolean(&apdu[0], true);
break;
case PROP_READ_ONLY:
/* FIXME: get the actual value */
apdu_len = encode_application_boolean(&apdu[0], true);
break;
case PROP_FILE_ACCESS_METHOD:
apdu_len = encode_application_enumerated(&apdu[0], FILE_STREAM_ACCESS);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0],
OBJECT_FILE, object_instance);
break;
case PROP_OBJECT_NAME:
sprintf(text_string, "FILE %d", object_instance);
characterstring_init_ansi(&char_string, text_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_FILE);
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
bacfile_name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_FILE_TYPE:
characterstring_init_ansi(&char_string, "TEXT");
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_FILE_SIZE:
apdu_len = encode_application_unsigned(&apdu[0],
bacfile_file_size(object_instance));
break;
case PROP_MODIFICATION_DATE:
/* FIXME: get the actual value instead of April Fool's Day */
bdate.year = 2006; /* AD */
bdate.month = 4; /* 1=Jan */
bdate.day = 1; /* 1..31 */
bdate.wday = 6; /* 1=Monday */
apdu_len = encode_application_date(&apdu[0], &bdate);
/* FIXME: get the actual value */
btime.hour = 7;
btime.min = 0;
btime.sec = 3;
btime.hundredths = 1;
apdu_len += encode_application_time(&apdu[apdu_len], &btime);
break;
case PROP_ARCHIVE:
/* 12.13.8 Archive
This property, of type BOOLEAN, indicates whether the File
object has been saved for historical or backup purposes. This
property shall be logical TRUE only if no changes have been
made to the file data by internal processes or through File
Access Services since the last time the object was archived.
*/
/* FIXME: get the actual value: note it may be inverse... */
apdu_len = encode_application_boolean(&apdu[0], true);
break;
case PROP_READ_ONLY:
/* FIXME: get the actual value */
apdu_len = encode_application_boolean(&apdu[0], true);
break;
case PROP_FILE_ACCESS_METHOD:
apdu_len =
encode_application_enumerated(&apdu[0], FILE_STREAM_ACCESS);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool bacfile_write_property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool bacfile_write_property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
int len = 0;
@@ -279,40 +290,40 @@ bool bacfile_write_property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_ARCHIVE:
/* 12.13.8 Archive
This property, of type BOOLEAN, indicates whether the File
object has been saved for historical or backup purposes. This
property shall be logical TRUE only if no changes have been
made to the file data by internal processes or through File
Access Services since the last time the object was archived. */
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
if (value.type.Boolean) {
/* FIXME: do something to wp_data->object_instance */
case PROP_ARCHIVE:
/* 12.13.8 Archive
This property, of type BOOLEAN, indicates whether the File
object has been saved for historical or backup purposes. This
property shall be logical TRUE only if no changes have been
made to the file data by internal processes or through File
Access Services since the last time the object was archived. */
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
if (value.type.Boolean) {
/* FIXME: do something to wp_data->object_instance */
} else {
/* FIXME: do something to wp_data->object_instance */
}
} else {
/* FIXME: do something to wp_data->object_instance */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
break;
case PROP_FILE_SIZE:
/* If the file size can be changed by writing to the file,
and File_Access_Method is STREAM_ACCESS, then this property
shall be writable. */
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
/* FIXME: do something with value.type.Unsigned
to wp_data->object_instance */
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_FILE_SIZE:
/* If the file size can be changed by writing to the file,
and File_Access_Method is STREAM_ACCESS, then this property
shall be writable. */
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
/* FIXME: do something with value.type.Unsigned
to wp_data->object_instance */
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -320,7 +331,8 @@ bool bacfile_write_property(BACNET_WRITE_PROPERTY_DATA * wp_data,
uint32_t bacfile_instance(char *filename)
uint32_t bacfile_instance(
char *filename)
{
uint32_t index = 0;
uint32_t instance = BACNET_MAX_INSTANCE + 1;
@@ -343,7 +355,8 @@ uint32_t bacfile_instance(char *filename)
/* Another way would be to store the */
/* invokeID and file instance in a list or table */
/* when the request was sent */
uint32_t bacfile_instance_from_tsm(uint8_t invokeID)
uint32_t bacfile_instance_from_tsm(
uint8_t invokeID)
{
BACNET_NPDU_DATA npdu_data = { 0 }; /* dummy for getting npdu length */
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
@@ -353,7 +366,7 @@ uint32_t bacfile_instance_from_tsm(uint8_t invokeID)
BACNET_ADDRESS dest; /* where the original packet was destined */
uint8_t apdu[MAX_PDU] = { 0 }; /* original APDU packet */
uint16_t apdu_len = 0; /* original APDU packet length */
uint16_t len = 0; /* apdu header length */
uint16_t len = 0; /* apdu header length */
BACNET_ATOMIC_READ_FILE_DATA data = { 0 };
uint32_t object_instance = BACNET_MAX_INSTANCE + 1; /* return value */
bool found = false;
@@ -383,7 +396,8 @@ uint32_t bacfile_instance_from_tsm(uint8_t invokeID)
}
#endif
bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA * data)
bool bacfile_read_data(
BACNET_ATOMIC_READ_FILE_DATA * data)
{
char *pFilename = NULL;
bool found = false;
@@ -395,8 +409,7 @@ bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA * data)
found = true;
pFile = fopen(pFilename, "rb");
if (pFile) {
(void) fseek(pFile,
data->type.stream.fileStartPosition, SEEK_SET);
(void) fseek(pFile, data->type.stream.fileStartPosition, SEEK_SET);
len = fread(octetstring_value(&data->fileData), 1,
data->type.stream.requestedOctetCount, pFile);
if (len < data->type.stream.requestedOctetCount)
@@ -417,7 +430,8 @@ bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA * data)
return found;
}
bool bacfile_write_stream_data(BACNET_ATOMIC_WRITE_FILE_DATA * data)
bool bacfile_write_stream_data(
BACNET_ATOMIC_WRITE_FILE_DATA * data)
{
char *pFilename = NULL;
bool found = false;
@@ -428,15 +442,15 @@ bool bacfile_write_stream_data(BACNET_ATOMIC_WRITE_FILE_DATA * data)
found = true;
/* open the file as a clean slate when starting at 0 */
if (data->type.stream.fileStartPosition == 0)
pFile = fopen(pFilename, "wb");
pFile = fopen(pFilename, "wb");
else
pFile = fopen(pFilename, "rb+");
pFile = fopen(pFilename, "rb+");
if (pFile) {
(void)fseek(pFile, data->type.stream.fileStartPosition, SEEK_SET);
(void) fseek(pFile, data->type.stream.fileStartPosition, SEEK_SET);
if (fwrite(octetstring_value(&data->fileData),
octetstring_length(&data->fileData),1,pFile) != 1) {
octetstring_length(&data->fileData), 1, pFile) != 1) {
}
}
fclose(pFile);
}
}
+78 -68
View File
@@ -31,15 +31,14 @@
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#define MAX_BINARY_INPUTS 5
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Binary_Input_Properties_Required[] =
{
static const int Binary_Input_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
@@ -51,14 +50,12 @@ static const int Binary_Input_Properties_Required[] =
-1
};
static const int Binary_Input_Properties_Optional[] =
{
static const int Binary_Input_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Binary_Input_Properties_Proprietary[] =
{
static const int Binary_Input_Properties_Proprietary[] = {
-1
};
@@ -80,7 +77,8 @@ void Binary_Input_Property_Lists(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Binary_Input_Valid_Instance(uint32_t object_instance)
bool Binary_Input_Valid_Instance(
uint32_t object_instance)
{
if (object_instance < MAX_BINARY_INPUTS)
return true;
@@ -90,7 +88,8 @@ bool Binary_Input_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Binary_Input_Count(void)
unsigned Binary_Input_Count(
void)
{
return MAX_BINARY_INPUTS;
}
@@ -98,12 +97,14 @@ unsigned Binary_Input_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Binary_Input_Index_To_Instance(unsigned index)
uint32_t Binary_Input_Index_To_Instance(
unsigned index)
{
return index;
}
void Binary_Input_Init(void)
void Binary_Input_Init(
void)
{
static bool initialized = false;
unsigned i;
@@ -123,7 +124,8 @@ void Binary_Input_Init(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
unsigned Binary_Input_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_BINARY_INPUTS;
@@ -134,8 +136,8 @@ unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
return index;
}
static BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t
object_instance)
static BACNET_BINARY_PV Binary_Input_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
unsigned index = 0;
@@ -148,7 +150,8 @@ static BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t
return value;
}
char *Binary_Input_Name(uint32_t object_instance)
char *Binary_Input_Name(
uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
@@ -163,13 +166,15 @@ char *Binary_Input_Name(uint32_t object_instance)
/* return apdu length, or -1 on error */
/* assumption - object already exists, and has been bounds checked */
int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
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)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_POLARITY polarity = POLARITY_NORMAL;
@@ -178,50 +183,54 @@ int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
(void) array_index;
Binary_Input_Init();
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:
/* note: you need to look up the actual value */
apdu_len =
encode_application_enumerated(&apdu[0],
Binary_Input_Present_Value(object_instance));
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;
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:
/* note: you need to look up the actual value */
apdu_len =
encode_application_enumerated(&apdu[0],
Binary_Input_Present_Value(object_instance));
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;
@@ -232,7 +241,8 @@ int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
#include <string.h>
#include "ctest.h"
void testBinaryInput(Test * pTest)
void testBinaryInput(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -248,8 +258,7 @@ void testBinaryInput(Test * pTest)
/* FIXME: we should do a lot more testing here... */
len = Binary_Input_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len >= 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -262,7 +271,8 @@ void testBinaryInput(Test * pTest)
}
#ifdef TEST_BINARY_INPUT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -279,5 +289,5 @@ int main(void)
return 0;
}
#endif /* TEST_BINARY_INPUT */
#endif /* TEST */
#endif /* TEST_BINARY_INPUT */
#endif /* TEST */
+195 -184
View File
@@ -32,7 +32,7 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_BINARY_OUTPUTS 6
@@ -48,8 +48,7 @@ static BACNET_BINARY_PV
static bool Binary_Output_Out_Of_Service[MAX_BINARY_OUTPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Binary_Output_Properties_Required[] =
{
static const int Binary_Output_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
@@ -63,14 +62,12 @@ static const int Binary_Output_Properties_Required[] =
-1
};
static const int Binary_Output_Properties_Optional[] =
{
static const int Binary_Output_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Binary_Output_Properties_Proprietary[] =
{
static const int Binary_Output_Properties_Proprietary[] = {
-1
};
@@ -89,7 +86,8 @@ void Binary_Output_Property_Lists(
return;
}
void Binary_Output_Init(void)
void Binary_Output_Init(
void)
{
unsigned i, j;
static bool initialized = false;
@@ -111,7 +109,8 @@ void Binary_Output_Init(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Binary_Output_Valid_Instance(uint32_t object_instance)
bool Binary_Output_Valid_Instance(
uint32_t object_instance)
{
if (object_instance < MAX_BINARY_OUTPUTS)
return true;
@@ -121,7 +120,8 @@ bool Binary_Output_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Binary_Output_Count(void)
unsigned Binary_Output_Count(
void)
{
return MAX_BINARY_OUTPUTS;
}
@@ -129,7 +129,8 @@ unsigned Binary_Output_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Binary_Output_Index_To_Instance(unsigned index)
uint32_t Binary_Output_Index_To_Instance(
unsigned index)
{
return index;
}
@@ -137,7 +138,8 @@ uint32_t Binary_Output_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Binary_Output_Instance_To_Index(uint32_t object_instance)
unsigned Binary_Output_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_BINARY_OUTPUTS;
@@ -147,8 +149,8 @@ unsigned Binary_Output_Instance_To_Index(uint32_t object_instance)
return index;
}
static BACNET_BINARY_PV Binary_Output_Present_Value(uint32_t
object_instance)
static BACNET_BINARY_PV Binary_Output_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -169,7 +171,8 @@ static BACNET_BINARY_PV Binary_Output_Present_Value(uint32_t
}
/* note: the object name must be unique within this device */
char *Binary_Output_Name(uint32_t object_instance)
char *Binary_Output_Name(
uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
@@ -182,14 +185,16 @@ char *Binary_Output_Name(uint32_t object_instance)
}
/* return apdu len, or -1 on error */
int Binary_Output_Encode_Property_APDU(uint8_t * apdu,
int Binary_Output_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)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int len = 0;
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
@@ -200,116 +205,121 @@ int Binary_Output_Encode_Property_APDU(uint8_t * apdu,
Binary_Output_Init();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_BINARY_OUTPUT,
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:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Binary_Output_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_OUTPUT);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Output_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&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);
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:
object_index = Binary_Output_Instance_To_Index(object_instance);
state = Binary_Output_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_POLARITY:
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index =
Binary_Output_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Binary_Output_Level[object_index][i] == BINARY_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
present_value = Binary_Output_Level[object_index][i];
len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index =
Binary_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Binary_Output_Level[object_index][array_index] ==
BINARY_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
present_value =
Binary_Output_Level[object_index][array_index];
len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
encode_application_object_id(&apdu[0], OBJECT_BINARY_OUTPUT,
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:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Binary_Output_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_OUTPUT);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Output_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&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);
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:
object_index = Binary_Output_Instance_To_Index(object_instance);
state = Binary_Output_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_POLARITY:
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index =
Binary_Output_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Binary_Output_Level[object_index][i] == BINARY_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
present_value = Binary_Output_Level[object_index][i];
len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
object_index =
Binary_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Binary_Output_Level[object_index][array_index] ==
BINARY_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
present_value =
Binary_Output_Level[object_index][array_index];
len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
}
break;
case PROP_RELINQUISH_DEFAULT:
present_value = RELINQUISH_DEFAULT;
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
break;
case PROP_RELINQUISH_DEFAULT:
present_value = RELINQUISH_DEFAULT;
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Binary_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Binary_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -330,78 +340,78 @@ bool Binary_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
priority = wp_data->priority;
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value.type.Enumerated >= MIN_BINARY_PV) &&
(value.type.Enumerated <= MAX_BINARY_PV)) {
level = (BACNET_BINARY_PV)value.type.Enumerated;
object_index =
Binary_Output_Instance_To_Index(wp_data->
object_instance);
priority--;
Binary_Output_Level[object_index][priority] = level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else if (priority == 6) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
priority = wp_data->priority;
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value.type.Enumerated >= MIN_BINARY_PV) &&
(value.type.Enumerated <= MAX_BINARY_PV)) {
level = (BACNET_BINARY_PV) value.type.Enumerated;
object_index =
Binary_Output_Instance_To_Index(wp_data->
object_instance);
priority--;
Binary_Output_Level[object_index][priority] = level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else if (priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = BINARY_NULL;
object_index =
Binary_Output_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Output_Level[object_index][priority] = level;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = BINARY_NULL;
object_index =
Binary_Output_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Output_Level[object_index][priority] = level;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Binary_Output_Instance_To_Index(wp_data->object_instance);
Binary_Output_Out_Of_Service[object_index] =
value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Binary_Output_Instance_To_Index(wp_data->object_instance);
Binary_Output_Out_Of_Service[object_index] =
value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -413,7 +423,8 @@ bool Binary_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
#include <string.h>
#include "ctest.h"
void testBinaryOutput(Test * pTest)
void testBinaryOutput(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -428,8 +439,7 @@ void testBinaryOutput(Test * pTest)
len = Binary_Output_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -442,7 +452,8 @@ void testBinaryOutput(Test * pTest)
}
#ifdef TEST_BINARY_OUTPUT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -459,5 +470,5 @@ int main(void)
return 0;
}
#endif /* TEST_BINARY_INPUT */
#endif /* TEST */
#endif /* TEST_BINARY_INPUT */
#endif /* TEST */
+188 -176
View File
@@ -32,7 +32,7 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_BINARY_VALUES 2
@@ -48,8 +48,7 @@ static BACNET_BINARY_PV
static bool Binary_Value_Out_Of_Service[MAX_BINARY_VALUES];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Binary_Value_Properties_Required[] =
{
static const int Binary_Value_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
@@ -60,16 +59,14 @@ static const int Binary_Value_Properties_Required[] =
-1
};
static const int Binary_Value_Properties_Optional[] =
{
static const int Binary_Value_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
static const int Binary_Value_Properties_Proprietary[] =
{
static const int Binary_Value_Properties_Proprietary[] = {
-1
};
@@ -88,7 +85,8 @@ void Binary_Value_Property_Lists(
return;
}
void Binary_Value_Init(void)
void Binary_Value_Init(
void)
{
unsigned i, j;
static bool initialized = false;
@@ -110,7 +108,8 @@ void Binary_Value_Init(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Binary_Value_Valid_Instance(uint32_t object_instance)
bool Binary_Value_Valid_Instance(
uint32_t object_instance)
{
if (object_instance < MAX_BINARY_VALUES)
return true;
@@ -120,7 +119,8 @@ bool Binary_Value_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Binary_Value_Count(void)
unsigned Binary_Value_Count(
void)
{
return MAX_BINARY_VALUES;
}
@@ -128,7 +128,8 @@ unsigned Binary_Value_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Binary_Value_Index_To_Instance(unsigned index)
uint32_t Binary_Value_Index_To_Instance(
unsigned index)
{
return index;
}
@@ -136,7 +137,8 @@ uint32_t Binary_Value_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Binary_Value_Instance_To_Index(uint32_t object_instance)
unsigned Binary_Value_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_BINARY_VALUES;
@@ -146,8 +148,8 @@ unsigned Binary_Value_Instance_To_Index(uint32_t object_instance)
return index;
}
static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t
object_instance)
static BACNET_BINARY_PV Binary_Value_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -168,7 +170,8 @@ static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t
}
/* note: the object name must be unique within this device */
char *Binary_Value_Name(uint32_t object_instance)
char *Binary_Value_Name(
uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
@@ -181,14 +184,16 @@ char *Binary_Value_Name(uint32_t object_instance)
}
/* return apdu len, or -1 on error */
int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
int Binary_Value_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)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int len = 0;
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
@@ -198,110 +203,116 @@ int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
Binary_Value_Init();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
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:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Binary_Value_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_VALUE);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Value_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&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);
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:
object_index = Binary_Value_Instance_To_Index(object_instance);
state = Binary_Value_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
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:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Binary_Value_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_VALUE);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Value_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&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);
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:
object_index = Binary_Value_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Binary_Value_Level[object_index][i] == BINARY_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
present_value = Binary_Value_Level[object_index][i];
len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index = Binary_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Binary_Value_Level[object_index][array_index] ==
BINARY_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
present_value =
Binary_Value_Level[object_index][array_index];
len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
state = Binary_Value_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index = Binary_Value_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Binary_Value_Level[object_index][i] == BINARY_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
present_value = Binary_Value_Level[object_index][i];
len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
object_index = Binary_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Binary_Value_Level[object_index][array_index] ==
BINARY_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
present_value =
Binary_Value_Level[object_index][array_index];
len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
}
break;
case PROP_RELINQUISH_DEFAULT:
present_value = RELINQUISH_DEFAULT;
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
break;
case PROP_RELINQUISH_DEFAULT:
present_value = RELINQUISH_DEFAULT;
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Binary_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -322,77 +333,77 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
priority = wp_data->priority;
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value.type.Enumerated >= MIN_BINARY_PV) &&
(value.type.Enumerated <= MAX_BINARY_PV)) {
level = (BACNET_BINARY_PV)value.type.Enumerated;
object_index =
Binary_Value_Instance_To_Index(wp_data->
object_instance);
priority--;
Binary_Value_Level[object_index][priority] = level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else if (priority == 6) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
priority = wp_data->priority;
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value.type.Enumerated >= MIN_BINARY_PV) &&
(value.type.Enumerated <= MAX_BINARY_PV)) {
level = (BACNET_BINARY_PV) value.type.Enumerated;
object_index =
Binary_Value_Instance_To_Index(wp_data->
object_instance);
priority--;
Binary_Value_Level[object_index][priority] = level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else if (priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = BINARY_NULL;
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Value_Level[object_index][priority] = level;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = BINARY_NULL;
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Value_Level[object_index][priority] = level;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
Binary_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
Binary_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -404,7 +415,8 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
#include <string.h>
#include "ctest.h"
void testBinary_Value(Test * pTest)
void testBinary_Value(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -419,8 +431,7 @@ void testBinary_Value(Test * pTest)
len = Binary_Value_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -433,7 +444,8 @@ void testBinary_Value(Test * pTest)
}
#ifdef TEST_BINARY_VALUE
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -450,5 +462,5 @@ int main(void)
return 0;
}
#endif /* TEST_BINARY_VALUE */
#endif /* TEST */
#endif /* TEST_BINARY_VALUE */
#endif /* TEST */
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+235 -208
View File
@@ -32,7 +32,7 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_LIGHTING_OUTPUTS 5
@@ -49,12 +49,12 @@
of the optional parameters, we represent them interally as
integers. */
typedef struct LightingCommand {
BACNET_LIGHTING_OPERATION operation;
uint8_t level; /* 0..100 percent, 255=not used */
uint8_t ramp_rate; /* 0..100 percent-per-second, 255=not used */
uint8_t step_increment; /* 0..100 amount to step, 255=not used */
uint16_t fade_time; /* 1..65535 seconds to transition, 0=not used */
uint16_t duration; /* 1..65535 minutes until relinquish, 0=not used */
BACNET_LIGHTING_OPERATION operation;
uint8_t level; /* 0..100 percent, 255=not used */
uint8_t ramp_rate; /* 0..100 percent-per-second, 255=not used */
uint8_t step_increment; /* 0..100 amount to step, 255=not used */
uint16_t fade_time; /* 1..65535 seconds to transition, 0=not used */
uint16_t duration; /* 1..65535 minutes until relinquish, 0=not used */
} BACNET_LIGHTING_COMMAND;
/* Here is our Priority Array. They are supposed to be Real, but */
@@ -76,51 +76,46 @@ static BACNET_LIGHTING_COMMAND Lighting_Command[MAX_LIGHTING_OUTPUTS];
/* we need to have our arrays initialized before answering any calls */
static bool Lighting_Output_Initialized = false;
int Lighting_Output_Encode_Lighting_Command(uint8_t * apdu,
int Lighting_Output_Encode_Lighting_Command(
uint8_t * apdu,
BACNET_LIGHTING_COMMAND * data)
{
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* total length of the apdu, return value */
int apdu_len = 0; /* total length of the apdu, return value */
int len = 0; /* total length of the apdu, return value */
float real_value = 0.0;
uint32_t unsigned_value = 0;
if (apdu) {
len = encode_context_enumerated(&apdu[apdu_len], 0,
data->operation);
len = encode_context_enumerated(&apdu[apdu_len], 0, data->operation);
apdu_len += len;
/* optional level? */
if (data->level != 255) {
real_value = data->level;
len = encode_context_real(&apdu[apdu_len], 1,
real_value);
len = encode_context_real(&apdu[apdu_len], 1, real_value);
apdu_len += len;
}
/* optional ramp-rate */
if (data->ramp_rate != 255) {
real_value = data->ramp_rate;
len = encode_context_real(&apdu[apdu_len], 2,
real_value);
len = encode_context_real(&apdu[apdu_len], 2, real_value);
apdu_len += len;
}
/* optional step increment */
if (data->step_increment != 255) {
real_value = data->step_increment;
len = encode_context_real(&apdu[apdu_len], 3,
real_value);
len = encode_context_real(&apdu[apdu_len], 3, real_value);
apdu_len += len;
}
/* optional fade time */
if (data->fade_time != 0) {
real_value = data->fade_time;
len = encode_context_real(&apdu[apdu_len], 4,
real_value);
len = encode_context_real(&apdu[apdu_len], 4, real_value);
apdu_len += len;
}
/* optional duration */
if (data->duration != 0) {
unsigned_value = data->duration;
len = encode_context_unsigned(&apdu[apdu_len], 5,
unsigned_value);
len = encode_context_unsigned(&apdu[apdu_len], 5, unsigned_value);
apdu_len += len;
}
}
@@ -128,18 +123,20 @@ int Lighting_Output_Encode_Lighting_Command(uint8_t * apdu,
return apdu_len;
}
int Lighting_Output_Decode_Lighting_Command(uint8_t * apdu,
unsigned apdu_max_len, BACNET_LIGHTING_COMMAND * data)
int Lighting_Output_Decode_Lighting_Command(
uint8_t * apdu,
unsigned apdu_max_len,
BACNET_LIGHTING_COMMAND * data)
{
int len = 0;
int apdu_len = 0;
int tag_len = 0;
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
int type = 0; /* for decoding */
int property = 0; /* for decoding */
int type = 0; /* for decoding */
int property = 0; /* for decoding */
uint32_t unsigned_value = 0;
int i = 0; /* loop counter */
int i = 0; /* loop counter */
float real_value = 0.0;
/* check for value pointers */
@@ -150,7 +147,9 @@ int Lighting_Output_Decode_Lighting_Command(uint8_t * apdu,
len = decode_tag_number_and_value(&apdu[apdu_len],
&tag_number, &len_value_type);
apdu_len += len;
len = decode_enumerated(&apdu[apdu_len], len_value_type, &data->operation);
len =
decode_enumerated(&apdu[apdu_len], len_value_type,
&data->operation);
apdu_len += len;
/* Tag 1: level - OPTIONAL */
if (decode_is_context_tag(&apdu[apdu_len], 1)) {
@@ -171,7 +170,8 @@ int Lighting_Output_Decode_Lighting_Command(uint8_t * apdu,
}
void Lighting_Output_Init(void)
void Lighting_Output_Init(
void)
{
unsigned i, j;
@@ -197,7 +197,8 @@ void Lighting_Output_Init(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Lighting_Output_Valid_Instance(uint32_t object_instance)
bool Lighting_Output_Valid_Instance(
uint32_t object_instance)
{
Lighting_Output_Init();
if (object_instance < MAX_LIGHTING_OUTPUTS)
@@ -208,7 +209,8 @@ bool Lighting_Output_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Lighting_Output_Count(void)
unsigned Lighting_Output_Count(
void)
{
Lighting_Output_Init();
return MAX_LIGHTING_OUTPUTS;
@@ -217,7 +219,8 @@ unsigned Lighting_Output_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Lighting_Output_Index_To_Instance(unsigned index)
uint32_t Lighting_Output_Index_To_Instance(
unsigned index)
{
Lighting_Output_Init();
return index;
@@ -226,7 +229,8 @@ uint32_t Lighting_Output_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Lighting_Output_Instance_To_Index(uint32_t object_instance)
unsigned Lighting_Output_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_LIGHTING_OUTPUTS;
@@ -237,7 +241,8 @@ unsigned Lighting_Output_Instance_To_Index(uint32_t object_instance)
return index;
}
float Lighting_Output_Present_Value(uint32_t object_instance)
float Lighting_Output_Present_Value(
uint32_t object_instance)
{
float value = LIGHTING_RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -257,10 +262,11 @@ float Lighting_Output_Present_Value(uint32_t object_instance)
return value;
}
unsigned Lighting_Output_Present_Value_Priority(uint32_t object_instance)
unsigned Lighting_Output_Present_Value_Priority(
uint32_t object_instance)
{
unsigned index = 0; /* instance to index conversion */
unsigned i = 0; /* loop counter */
unsigned index = 0; /* instance to index conversion */
unsigned i = 0; /* loop counter */
unsigned priority = 0; /* return value */
Lighting_Output_Init();
@@ -277,8 +283,10 @@ unsigned Lighting_Output_Present_Value_Priority(uint32_t object_instance)
return priority;
}
bool Lighting_Output_Present_Value_Set(uint32_t object_instance,
float value, unsigned priority)
bool Lighting_Output_Present_Value_Set(
uint32_t object_instance,
float value,
unsigned priority)
{
unsigned index = 0;
bool status = false;
@@ -288,7 +296,7 @@ bool Lighting_Output_Present_Value_Set(uint32_t object_instance,
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value >= 0.0) && (value <= 100.0)) {
Lighting_Output_Level[index][priority-1] = (uint8_t) value;
Lighting_Output_Level[index][priority - 1] = (uint8_t) value;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
@@ -302,7 +310,8 @@ bool Lighting_Output_Present_Value_Set(uint32_t object_instance,
return status;
}
bool Lighting_Output_Present_Value_Relinquish(uint32_t object_instance,
bool Lighting_Output_Present_Value_Relinquish(
uint32_t object_instance,
int priority)
{
unsigned index = 0;
@@ -312,7 +321,7 @@ bool Lighting_Output_Present_Value_Relinquish(uint32_t object_instance,
if (index < MAX_LIGHTING_OUTPUTS) {
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ )) {
Lighting_Output_Level[index][priority-1] = LIGHTING_LEVEL_NULL;
Lighting_Output_Level[index][priority - 1] = LIGHTING_LEVEL_NULL;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
@@ -326,7 +335,8 @@ bool Lighting_Output_Present_Value_Relinquish(uint32_t object_instance,
return status;
}
float Lighting_Output_Progress_Value(uint32_t object_instance)
float Lighting_Output_Progress_Value(
uint32_t object_instance)
{
float value = LIGHTING_RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -341,7 +351,8 @@ float Lighting_Output_Progress_Value(uint32_t object_instance)
}
/* note: the object name must be unique within this device */
char *Lighting_Output_Name(uint32_t object_instance)
char *Lighting_Output_Name(
uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
@@ -354,14 +365,16 @@ char *Lighting_Output_Name(uint32_t object_instance)
}
/* return apdu len, or -1 on error */
int Lighting_Output_Encode_Property_APDU(uint8_t * apdu,
int Lighting_Output_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)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int len = 0;
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
float real_value = (float) 1.414;
@@ -371,118 +384,129 @@ int Lighting_Output_Encode_Property_APDU(uint8_t * apdu,
Lighting_Output_Init();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_LIGHTING_OUTPUT,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
/* object name must be unique in this device. */
/* FIXME: description could be writable and different than object name */
characterstring_init_ansi(&char_string,
Lighting_Output_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_LIGHTING_OUTPUT);
break;
case PROP_PRESENT_VALUE:
real_value = Lighting_Output_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_PROGRESS_VALUE:
real_value = Lighting_Output_Progress_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_LIGHTING_COMMAND:
apdu_len = Lighting_Output_Encode_Lighting_Command(&apdu[0],
&Lighting_Command[object_instance]);
break;
case PROP_STATUS_FLAGS:
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:
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index = Lighting_Output_Instance_To_Index(object_instance);
state = Lighting_Output_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index =
Lighting_Output_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Lighting_Output_Level[object_index][i] == LIGHTING_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Lighting_Output_Level[object_index][i];
len = encode_application_real(&apdu[apdu_len], real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index =
Lighting_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Lighting_Output_Level[object_index][array_index - 1] ==
LIGHTING_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Lighting_Output_Level[object_index][array_index - 1];
apdu_len = encode_application_real(&apdu[0], real_value);
encode_application_object_id(&apdu[0], OBJECT_LIGHTING_OUTPUT,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
/* object name must be unique in this device. */
/* FIXME: description could be writable and different than object name */
characterstring_init_ansi(&char_string,
Lighting_Output_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_LIGHTING_OUTPUT);
break;
case PROP_PRESENT_VALUE:
real_value = Lighting_Output_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_PROGRESS_VALUE:
real_value = Lighting_Output_Progress_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_LIGHTING_COMMAND:
apdu_len = Lighting_Output_Encode_Lighting_Command(&apdu[0],
&Lighting_Command[object_instance]);
break;
case PROP_STATUS_FLAGS:
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:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index = Lighting_Output_Instance_To_Index(object_instance);
state = Lighting_Output_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index =
Lighting_Output_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Lighting_Output_Level[object_index][i] ==
LIGHTING_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Lighting_Output_Level[object_index][i];
len =
encode_application_real(&apdu[apdu_len],
real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
object_index =
Lighting_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Lighting_Output_Level[object_index][array_index - 1] ==
LIGHTING_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Lighting_Output_Level[object_index][array_index -
1];
apdu_len =
encode_application_real(&apdu[0], real_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
}
break;
case PROP_RELINQUISH_DEFAULT:
real_value = LIGHTING_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
break;
case PROP_RELINQUISH_DEFAULT:
real_value = LIGHTING_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Lighting_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Lighting_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -502,68 +526,70 @@ bool Lighting_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
status =
Lighting_Output_Present_Value_Set(wp_data->object_instance,
value.type.Real, wp_data->priority);
if (wp_data->priority == 6) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
status =
Lighting_Output_Present_Value_Set(wp_data->object_instance,
value.type.Real, wp_data->priority);
if (wp_data->priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = LIGHTING_LEVEL_NULL;
object_index =
Lighting_Output_Instance_To_Index(wp_data->
object_instance);
status =
Lighting_Output_Present_Value_Relinquish(wp_data->
object_instance, wp_data->priority);
if (wp_data->priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = LIGHTING_LEVEL_NULL;
object_index =
Lighting_Output_Instance_To_Index(wp_data->object_instance);
status =
Lighting_Output_Present_Value_Relinquish(wp_data->
object_instance, wp_data->priority);
if (wp_data->priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
break;
case PROP_LIGHTING_COMMAND:
/* FIXME: error checking? */
Lighting_Output_Decode_Lighting_Command(wp_data->application_data,
wp_data->application_data_len,
&Lighting_Command[wp_data->object_instance]);
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Lighting_Output_Instance_To_Index(wp_data->
object_instance);
Lighting_Output_Out_Of_Service[object_index] =
value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_LIGHTING_COMMAND:
/* FIXME: error checking? */
Lighting_Output_Decode_Lighting_Command(wp_data->application_data,
wp_data->application_data_len,
&Lighting_Command[wp_data->object_instance]);
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Lighting_Output_Instance_To_Index(wp_data->object_instance);
Lighting_Output_Out_Of_Service[object_index] =
value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -575,7 +601,8 @@ bool Lighting_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
#include <string.h>
#include "ctest.h"
void testLightingOutput(Test * pTest)
void testLightingOutput(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -590,8 +617,7 @@ void testLightingOutput(Test * pTest)
len = Lighting_Output_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -604,7 +630,8 @@ void testLightingOutput(Test * pTest)
}
#ifdef TEST_LIGHTING_OUTPUT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -621,5 +648,5 @@ int main(void)
return 0;
}
#endif /* TEST_LIGHTING_INPUT */
#endif /* TEST */
#endif /* TEST_LIGHTING_INPUT */
#endif /* TEST */
+139 -131
View File
@@ -32,14 +32,13 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_LIFE_SAFETY_POINTS 7
/* Here are our stored levels.*/
static BACNET_LIFE_SAFETY_MODE
Life_Safety_Point_Mode[MAX_LIFE_SAFETY_POINTS];
static BACNET_LIFE_SAFETY_MODE Life_Safety_Point_Mode[MAX_LIFE_SAFETY_POINTS];
static BACNET_LIFE_SAFETY_STATE
Life_Safety_Point_State[MAX_LIFE_SAFETY_POINTS];
static BACNET_SILENCED_STATE
@@ -51,8 +50,7 @@ static BACNET_LIFE_SAFETY_OPERATION
static bool Life_Safety_Point_Out_Of_Service[MAX_LIFE_SAFETY_POINTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Life_Safety_Point_Properties_Required[] =
{
static const int Life_Safety_Point_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
@@ -68,14 +66,12 @@ static const int Life_Safety_Point_Properties_Required[] =
-1
};
static const int Life_Safety_Point_Properties_Optional[] =
{
static const int Life_Safety_Point_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Life_Safety_Point_Properties_Proprietary[] =
{
static const int Life_Safety_Point_Properties_Proprietary[] = {
-1
};
@@ -94,7 +90,8 @@ void Life_Safety_Point_Property_Lists(
return;
}
void Life_Safety_Point_Init(void)
void Life_Safety_Point_Init(
void)
{
static bool initialized = false;
unsigned i;
@@ -106,8 +103,7 @@ void Life_Safety_Point_Init(void)
for (i = 0; i < MAX_LIFE_SAFETY_POINTS; i++) {
Life_Safety_Point_Mode[i] = LIFE_SAFETY_MODE_DEFAULT;
Life_Safety_Point_State[i] = LIFE_SAFETY_STATE_QUIET;
Life_Safety_Point_Silenced_State[i] =
SILENCED_STATE_UNSILENCED;
Life_Safety_Point_Silenced_State[i] = SILENCED_STATE_UNSILENCED;
Life_Safety_Point_Operation[i] = LIFE_SAFETY_OPERATION_NONE;
}
}
@@ -118,7 +114,8 @@ void Life_Safety_Point_Init(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Life_Safety_Point_Valid_Instance(uint32_t object_instance)
bool Life_Safety_Point_Valid_Instance(
uint32_t object_instance)
{
Life_Safety_Point_Init();
if (object_instance < MAX_LIFE_SAFETY_POINTS)
@@ -129,7 +126,8 @@ bool Life_Safety_Point_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Life_Safety_Point_Count(void)
unsigned Life_Safety_Point_Count(
void)
{
Life_Safety_Point_Init();
return MAX_LIFE_SAFETY_POINTS;
@@ -138,7 +136,8 @@ unsigned Life_Safety_Point_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Life_Safety_Point_Index_To_Instance(unsigned index)
uint32_t Life_Safety_Point_Index_To_Instance(
unsigned index)
{
Life_Safety_Point_Init();
return index;
@@ -147,7 +146,8 @@ uint32_t Life_Safety_Point_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Life_Safety_Point_Instance_To_Index(uint32_t object_instance)
unsigned Life_Safety_Point_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_LIFE_SAFETY_POINTS;
@@ -158,8 +158,8 @@ unsigned Life_Safety_Point_Instance_To_Index(uint32_t object_instance)
return index;
}
static BACNET_LIFE_SAFETY_STATE Life_Safety_Point_Present_Value(uint32_t
object_instance)
static BACNET_LIFE_SAFETY_STATE Life_Safety_Point_Present_Value(
uint32_t object_instance)
{
BACNET_LIFE_SAFETY_STATE present_value = LIFE_SAFETY_STATE_QUIET;
unsigned index = 0;
@@ -173,7 +173,8 @@ static BACNET_LIFE_SAFETY_STATE Life_Safety_Point_Present_Value(uint32_t
}
/* note: the object name must be unique within this device */
char *Life_Safety_Point_Name(uint32_t object_instance)
char *Life_Safety_Point_Name(
uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
@@ -186,14 +187,16 @@ char *Life_Safety_Point_Name(uint32_t object_instance)
}
/* return apdu len, or -1 on error */
int Life_Safety_Point_Encode_Property_APDU(uint8_t * apdu,
int Life_Safety_Point_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)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int len = 0;
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_LIFE_SAFETY_STATE present_value = LIFE_SAFETY_STATE_QUIET;
@@ -204,88 +207,93 @@ int Life_Safety_Point_Encode_Property_APDU(uint8_t * apdu,
bool state = false;
BACNET_RELIABILITY reliability = RELIABILITY_NO_FAULT_DETECTED;
(void) array_index; /* currently not used */
(void) array_index; /* currently not used */
Life_Safety_Point_Init();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_LIFE_SAFETY_POINT,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Life_Safety_Point_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_LIFE_SAFETY_POINT);
break;
case PROP_PRESENT_VALUE:
present_value = Life_Safety_Point_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
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:
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index =
Life_Safety_Point_Instance_To_Index(object_instance);
state = Life_Safety_Point_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_RELIABILITY:
/* see standard for details about this property */
reliability = RELIABILITY_NO_FAULT_DETECTED;
apdu_len = encode_application_enumerated(&apdu[0], reliability);
break;
case PROP_MODE:
object_index =
Life_Safety_Point_Instance_To_Index(object_instance);
mode = Life_Safety_Point_Mode[object_index];
apdu_len = encode_application_enumerated(&apdu[0], mode);
break;
case PROP_ACCEPTED_MODES:
for (mode = MIN_LIFE_SAFETY_MODE; mode < MAX_LIFE_SAFETY_MODE;
mode++) {
len = encode_application_enumerated(&apdu[apdu_len], mode);
apdu_len += len;
}
break;
case PROP_SILENCED:
object_index =
Life_Safety_Point_Instance_To_Index(object_instance);
silenced_state = Life_Safety_Point_Silenced_State[object_index];
apdu_len = encode_application_enumerated(&apdu[0], silenced_state);
break;
case PROP_OPERATION_EXPECTED:
object_index =
Life_Safety_Point_Instance_To_Index(object_instance);
operation = Life_Safety_Point_Operation[object_index];
apdu_len = encode_application_enumerated(&apdu[0], operation);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_LIFE_SAFETY_POINT, object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Life_Safety_Point_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_LIFE_SAFETY_POINT);
break;
case PROP_PRESENT_VALUE:
present_value = Life_Safety_Point_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
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:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index =
Life_Safety_Point_Instance_To_Index(object_instance);
state = Life_Safety_Point_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_RELIABILITY:
/* see standard for details about this property */
reliability = RELIABILITY_NO_FAULT_DETECTED;
apdu_len = encode_application_enumerated(&apdu[0], reliability);
break;
case PROP_MODE:
object_index =
Life_Safety_Point_Instance_To_Index(object_instance);
mode = Life_Safety_Point_Mode[object_index];
apdu_len = encode_application_enumerated(&apdu[0], mode);
break;
case PROP_ACCEPTED_MODES:
for (mode = MIN_LIFE_SAFETY_MODE; mode < MAX_LIFE_SAFETY_MODE;
mode++) {
len = encode_application_enumerated(&apdu[apdu_len], mode);
apdu_len += len;
}
break;
case PROP_SILENCED:
object_index =
Life_Safety_Point_Instance_To_Index(object_instance);
silenced_state = Life_Safety_Point_Silenced_State[object_index];
apdu_len = encode_application_enumerated(&apdu[0], silenced_state);
break;
case PROP_OPERATION_EXPECTED:
object_index =
Life_Safety_Point_Instance_To_Index(object_instance);
operation = Life_Safety_Point_Operation[object_index];
apdu_len = encode_application_enumerated(&apdu[0], operation);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Life_Safety_Point_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Life_Safety_Point_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -304,42 +312,42 @@ bool Life_Safety_Point_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_MODE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
if ((value.type.Enumerated >= MIN_LIFE_SAFETY_MODE) &&
(value.type.Enumerated <= MIN_LIFE_SAFETY_MODE)) {
case PROP_MODE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
if ((value.type.Enumerated >= MIN_LIFE_SAFETY_MODE) &&
(value.type.Enumerated <= MIN_LIFE_SAFETY_MODE)) {
object_index =
Life_Safety_Point_Instance_To_Index(wp_data->
object_instance);
Life_Safety_Point_Mode[object_index] =
value.type.Enumerated;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Life_Safety_Point_Instance_To_Index(wp_data->
object_instance);
Life_Safety_Point_Mode[object_index] =
value.type.Enumerated;
Life_Safety_Point_Out_Of_Service[object_index] =
value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Life_Safety_Point_Instance_To_Index(wp_data->
object_instance);
Life_Safety_Point_Out_Of_Service[object_index] =
value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -351,7 +359,8 @@ bool Life_Safety_Point_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
#include <string.h>
#include "ctest.h"
void testLifeSafetyPoint(Test * pTest)
void testLifeSafetyPoint(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -366,8 +375,7 @@ void testLifeSafetyPoint(Test * pTest)
len = Life_Safety_Point_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -380,7 +388,8 @@ void testLifeSafetyPoint(Test * pTest)
}
#ifdef TEST_LIFE_SAFETY_POINT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -397,6 +406,5 @@ int main(void)
return 0;
}
#endif /* TEST_LIFE_SAFETY_POINT */
#endif /* TEST */
#endif /* TEST_LIFE_SAFETY_POINT */
#endif /* TEST */
+202 -189
View File
@@ -32,7 +32,7 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_MULTISTATE_OUTPUTS 4
@@ -53,8 +53,7 @@ static uint8_t
static bool Multistate_Output_Out_Of_Service[MAX_MULTISTATE_OUTPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Multistate_Output_Properties_Required[] =
{
static const int Multistate_Output_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
@@ -68,14 +67,12 @@ static const int Multistate_Output_Properties_Required[] =
-1
};
static const int Multistate_Output_Properties_Optional[] =
{
static const int Multistate_Output_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Multistate_Output_Properties_Proprietary[] =
{
static const int Multistate_Output_Properties_Proprietary[] = {
-1
};
@@ -94,7 +91,8 @@ void Multistate_Output_Property_Lists(
return;
}
void Multistate_Output_Init(void)
void Multistate_Output_Init(
void)
{
unsigned i, j;
static bool initialized = false;
@@ -116,7 +114,8 @@ void Multistate_Output_Init(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Multistate_Output_Valid_Instance(uint32_t object_instance)
bool Multistate_Output_Valid_Instance(
uint32_t object_instance)
{
if (object_instance < MAX_MULTISTATE_OUTPUTS)
return true;
@@ -126,7 +125,8 @@ bool Multistate_Output_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Multistate_Output_Count(void)
unsigned Multistate_Output_Count(
void)
{
return MAX_MULTISTATE_OUTPUTS;
}
@@ -134,7 +134,8 @@ unsigned Multistate_Output_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Multistate_Output_Index_To_Instance(unsigned index)
uint32_t Multistate_Output_Index_To_Instance(
unsigned index)
{
return index;
}
@@ -142,7 +143,8 @@ uint32_t Multistate_Output_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Multistate_Output_Instance_To_Index(uint32_t object_instance)
unsigned Multistate_Output_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_MULTISTATE_OUTPUTS;
@@ -152,7 +154,8 @@ unsigned Multistate_Output_Instance_To_Index(uint32_t object_instance)
return index;
}
static uint32_t Multistate_Output_Present_Value(uint32_t object_instance)
static uint32_t Multistate_Output_Present_Value(
uint32_t object_instance)
{
uint32_t value = MULTISTATE_RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -173,7 +176,8 @@ static uint32_t Multistate_Output_Present_Value(uint32_t object_instance)
}
/* note: the object name must be unique within this device */
char *Multistate_Output_Name(uint32_t object_instance)
char *Multistate_Output_Name(
uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
@@ -186,14 +190,16 @@ char *Multistate_Output_Name(uint32_t object_instance)
}
/* return apdu len, or -1 on error */
int Multistate_Output_Encode_Property_APDU(uint8_t * apdu,
int Multistate_Output_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)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int len = 0;
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
uint32_t present_value = 0;
@@ -203,122 +209,128 @@ int Multistate_Output_Encode_Property_APDU(uint8_t * apdu,
Multistate_Output_Init();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_MULTI_STATE_OUTPUT,
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:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Multistate_Output_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_MULTI_STATE_OUTPUT);
break;
case PROP_PRESENT_VALUE:
present_value = Multistate_Output_Present_Value(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);
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:
object_index =
Multistate_Output_Instance_To_Index(object_instance);
state = Multistate_Output_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
encode_application_object_id(&apdu[0],
OBJECT_MULTI_STATE_OUTPUT, 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:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Multistate_Output_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_MULTI_STATE_OUTPUT);
break;
case PROP_PRESENT_VALUE:
present_value = Multistate_Output_Present_Value(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);
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:
object_index =
Multistate_Output_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Multistate_Output_Level[object_index][i] ==
MULTISTATE_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
present_value =
Multistate_Output_Level[object_index][i];
len =
encode_application_unsigned(&apdu[apdu_len],
present_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index =
Multistate_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Multistate_Output_Level[object_index][array_index -
1] == MULTISTATE_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
present_value =
Multistate_Output_Level[object_index][array_index -
1];
apdu_len =
encode_application_unsigned(&apdu[0], present_value);
state = Multistate_Output_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index =
Multistate_Output_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Multistate_Output_Level[object_index][i] ==
MULTISTATE_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
present_value =
Multistate_Output_Level[object_index][i];
len =
encode_application_unsigned(&apdu[apdu_len],
present_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
object_index =
Multistate_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Multistate_Output_Level[object_index][array_index -
1] == MULTISTATE_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
present_value =
Multistate_Output_Level[object_index][array_index -
1];
apdu_len =
encode_application_unsigned(&apdu[0],
present_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
}
break;
case PROP_RELINQUISH_DEFAULT:
present_value = MULTISTATE_RELINQUISH_DEFAULT;
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_NUMBER_OF_STATES:
apdu_len = encode_application_unsigned(&apdu[apdu_len],
MULTISTATE_NUMBER_OF_STATES);
break;
break;
case PROP_RELINQUISH_DEFAULT:
present_value = MULTISTATE_RELINQUISH_DEFAULT;
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_NUMBER_OF_STATES:
apdu_len = encode_application_unsigned(&apdu[apdu_len],
MULTISTATE_NUMBER_OF_STATES);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Multistate_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Multistate_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -339,81 +351,81 @@ bool Multistate_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
priority = wp_data->priority;
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value.type.Unsigned_Int <= MULTISTATE_NUMBER_OF_STATES)) {
level = value.type.Unsigned_Int;
object_index =
Multistate_Output_Instance_To_Index(wp_data->
object_instance);
priority--;
Multistate_Output_Level[object_index][priority] =
(uint8_t) level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else if (priority == 6) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
priority = wp_data->priority;
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value.type.Unsigned_Int <= MULTISTATE_NUMBER_OF_STATES)) {
level = value.type.Unsigned_Int;
object_index =
Multistate_Output_Instance_To_Index(wp_data->
object_instance);
priority--;
Multistate_Output_Level[object_index][priority] =
(uint8_t) level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else if (priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = MULTISTATE_NULL;
object_index =
Multistate_Output_Instance_To_Index(wp_data->
object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Multistate_Output_Level[object_index][priority] =
(uint8_t) level;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = MULTISTATE_NULL;
object_index =
Multistate_Output_Instance_To_Index(wp_data->
object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Multistate_Output_Level[object_index][priority] =
(uint8_t) level;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Multistate_Output_Instance_To_Index(wp_data->
object_instance);
Multistate_Output_Out_Of_Service[object_index] =
value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Multistate_Output_Instance_To_Index(wp_data->
object_instance);
Multistate_Output_Out_Of_Service[object_index] =
value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -425,7 +437,8 @@ bool Multistate_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
#include <string.h>
#include "ctest.h"
void testMultistateOutput(Test * pTest)
void testMultistateOutput(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -440,8 +453,7 @@ void testMultistateOutput(Test * pTest)
len = Multistate_Output_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -454,7 +466,8 @@ void testMultistateOutput(Test * pTest)
}
#ifdef TEST_MULTISTATE_OUTPUT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -471,5 +484,5 @@ int main(void)
return 0;
}
#endif /* TEST_BINARY_INPUT */
#endif /* TEST */
#endif /* TEST_BINARY_INPUT */
#endif /* TEST */
+37 -31
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -61,9 +61,11 @@ static bool End_Of_File_Detected = false;
static bool Error_Detected = false;
static uint8_t Current_Invoke_ID = 0;
static void Atomic_Read_File_Error_Handler(BACNET_ADDRESS * src,
static void Atomic_Read_File_Error_Handler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void) src;
@@ -74,43 +76,47 @@ static void Atomic_Read_File_Error_Handler(BACNET_ADDRESS * src,
Error_Detected = true;
}
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason, bool server)
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
(void) server;
printf("\r\nBACnet Abort!\r\n");
printf("Abort Reason: %s\r\n",
bactext_abort_reason_name(abort_reason));
printf("Abort Reason: %s\r\n", bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("\r\nBACnet Reject!\r\n");
printf("Reject Reason: %s\r\n",
bactext_reject_reason_name(reject_reason));
printf("Reject Reason: %s\r\n", bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
static void AtomicReadFileAckHandler(uint8_t * service_request,
static void AtomicReadFileAckHandler(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
{
int len = 0;
BACNET_ATOMIC_READ_FILE_DATA data;
FILE *pFile = NULL; /* stream pointer */
FILE *pFile = NULL; /* stream pointer */
size_t octets_written = 0;
(void) src; /* FIXME: validate the source address matches */
len = arf_ack_decode_service_request(service_request,
service_len, &data);
(void) src; /* FIXME: validate the source address matches */
len = arf_ack_decode_service_request(service_request, service_len, &data);
if (len > 0) {
/* validate the parameters before storing data */
if ((data.access == FILE_STREAM_ACCESS) &&
@@ -131,8 +137,7 @@ static void AtomicReadFileAckHandler(uint8_t * service_request,
Local_File_Name);
else
printf("\r%u bytes",
(data.type.stream.fileStartPosition +
octets_written));
(data.type.stream.fileStartPosition + octets_written));
fclose(pFile);
}
if (data.endOfFile) {
@@ -143,8 +148,10 @@ static void AtomicReadFileAckHandler(uint8_t * service_request,
}
}
static void LocalIAmHandler(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
static void LocalIAmHandler(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
uint32_t device_id = 0;
@@ -164,15 +171,14 @@ static void LocalIAmHandler(uint8_t * service_request,
return;
}
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
LocalIAmHandler);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, LocalIAmHandler);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
@@ -190,7 +196,9 @@ static void Init_Service_Handlers(void)
apdu_set_reject_handler(MyRejectHandler);
}
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
@@ -237,8 +245,7 @@ int main(int argc, char *argv[])
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
@@ -253,8 +260,7 @@ int main(int argc, char *argv[])
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds -
last_seconds) * 1000));
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
if (End_Of_File_Detected || Error_Detected)
break;
/* wait until the device is bound, or timeout and quit */
+28 -23
View File
@@ -29,7 +29,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#define PRINT_ENABLED 1
@@ -66,51 +66,57 @@ static int32_t Target_Object_Index = BACNET_ARRAY_ALL;
static BACNET_ADDRESS Target_Address;
static bool Error_Detected = false;
static void MyErrorHandler(BACNET_ADDRESS * src,
static void MyErrorHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Error: %s: %s\r\n",
bactext_error_class_name((int)error_class),
bactext_error_code_name((int)error_code));
bactext_error_class_name((int) error_class),
bactext_error_code_name((int) error_code));
Error_Detected = true;
}
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason, bool server)
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
(void) server;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name((int)abort_reason));
bactext_abort_reason_name((int) abort_reason));
Error_Detected = true;
}
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name((int)reject_reason));
bactext_reject_reason_name((int) reject_reason));
Error_Detected = true;
}
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
handler_i_am_bind);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
@@ -122,13 +128,14 @@ static void Init_Service_Handlers(void)
apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property_ack);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY,
MyErrorHandler);
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
@@ -186,8 +193,7 @@ int main(int argc, char *argv[])
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
@@ -202,8 +208,7 @@ int main(int argc, char *argv[])
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds -
last_seconds) * 1000));
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
if (Error_Detected)
break;
/* wait until the device is bound, or timeout and quit */
+29 -29
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -56,15 +56,16 @@ static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* global variables used in this file */
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
static BACNET_ADDRESS Target_Address;
static BACNET_REINITIALIZED_STATE Reinitialize_State =
BACNET_REINIT_COLDSTART;
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_COLDSTART;
static char *Reinitialize_Password = NULL;
static bool Error_Detected = false;
static void MyErrorHandler(BACNET_ADDRESS * src,
static void MyErrorHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void) src;
@@ -75,30 +76,34 @@ static void MyErrorHandler(BACNET_ADDRESS * src,
Error_Detected = true;
}
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason, bool server)
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
(void) server;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name(abort_reason));
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name(reject_reason));
printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
void MyReinitializeDeviceSimpleAckHandler(BACNET_ADDRESS * src,
void MyReinitializeDeviceSimpleAckHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id)
{
(void) src;
@@ -106,15 +111,14 @@ void MyReinitializeDeviceSimpleAckHandler(BACNET_ADDRESS * src,
printf("ReinitializeDevice Acknowledged!\r\n");
}
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
handler_i_am_bind);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
@@ -133,7 +137,9 @@ static void Init_Service_Handlers(void)
apdu_set_reject_handler(MyRejectHandler);
}
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
@@ -188,19 +194,14 @@ int main(int argc, char *argv[])
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
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);
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
@@ -208,8 +209,7 @@ int main(int argc, char *argv[])
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds -
last_seconds) * 1000));
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
if (Error_Detected)
break;
/* wait until the device is bound, or timeout and quit */
+11 -12
View File
@@ -55,13 +55,12 @@
/* buffers used for receiving */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS,
handler_who_has);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS, handler_who_has);
/* set the handler for all the services we don't implement */
/* It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
@@ -83,8 +82,7 @@ static void Init_Service_Handlers(void)
apdu_set_confirmed_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
handler_reinitialize_device);
apdu_set_unconfirmed_handler
(SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION,
handler_timesync_utc);
(SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, handler_timesync_utc);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION,
handler_timesync);
/* handle communication so we can shutup when asked */
@@ -93,12 +91,15 @@ static void Init_Service_Handlers(void)
handler_device_communication_control);
}
static void cleanup(void)
static void cleanup(
void)
{
datalink_cleanup();
}
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
@@ -147,9 +148,7 @@ int main(int argc, char *argv[])
"BACnet Stack Version %s\n"
"BACnet Device ID: %u\n"
"Max APDU: %d\n",
BACnet_Version,
Device_Object_Instance_Number(),
MAX_APDU);
BACnet_Version, Device_Object_Instance_Number(), MAX_APDU);
Init_Service_Handlers();
BIP_Debug = true;
if (!datalink_init(getenv("BACNET_IFACE")))
+19 -15
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "config.h"
@@ -56,35 +56,38 @@ static int32_t Target_Object_Instance_Max = BACNET_MAX_INSTANCE;
static bool Error_Detected = false;
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason, bool server)
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
(void) server;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name(abort_reason));
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name(reject_reason));
printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
@@ -94,8 +97,7 @@ static void Init_Service_Handlers(void)
handler_read_property);
/* handle the reply (request) coming in */
apdu_set_unconfirmed_handler
(SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION,
handler_timesync_utc);
(SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, handler_timesync_utc);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION,
handler_timesync);
/* handle any errors coming back */
@@ -103,7 +105,9 @@ static void Init_Service_Handlers(void)
apdu_set_reject_handler(MyRejectHandler);
}
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
+9 -9
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -49,15 +49,14 @@
#include "client.h"
#include "txbuf.h"
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
handler_i_am_bind);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
@@ -67,7 +66,9 @@ static void Init_Service_Handlers(void)
handler_read_property);
}
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
char *value_string = NULL;
bool status = false;
@@ -162,8 +163,7 @@ int main(int argc, char *argv[])
cov_data.listOfValues.priority = BACNET_NO_PRIORITY;
/* optional index */
if (argc > 10)
cov_data.listOfValues.propertyArrayIndex =
strtol(argv[10], NULL, 0);
cov_data.listOfValues.propertyArrayIndex = strtol(argv[10], NULL, 0);
else
cov_data.listOfValues.propertyArrayIndex = BACNET_ARRAY_ALL;
+20 -17
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -59,35 +59,38 @@ static char *Target_Object_Name = NULL;
static bool Error_Detected = false;
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason, bool server)
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
(void) server;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name(abort_reason));
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name(reject_reason));
printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
@@ -96,14 +99,15 @@ static void Init_Service_Handlers(void)
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the reply (request) coming back */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_HAVE,
handler_i_have);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_HAVE, handler_i_have);
/* handle any errors coming back */
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
@@ -157,8 +161,7 @@ int main(int argc, char *argv[])
if (argc < 3)
Send_WhoHas_Name(-1, -1, Target_Object_Name);
else
Send_WhoHas_Object(-1, -1,
Target_Object_Type, Target_Object_Instance);
Send_WhoHas_Object(-1, -1, Target_Object_Type, Target_Object_Instance);
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
+21 -16
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -55,35 +55,38 @@ static int32_t Target_Object_Instance_Max = BACNET_MAX_INSTANCE;
static bool Error_Detected = false;
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason, bool server)
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
(void) server;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name(abort_reason));
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name(reject_reason));
printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
@@ -92,14 +95,14 @@ static void Init_Service_Handlers(void)
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the reply (request) coming back */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
handler_i_am_add);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_add);
/* handle any errors coming back */
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
static void print_address_cache(void)
static void print_address_cache(
void)
{
int i, j;
BACNET_ADDRESS address;
@@ -120,7 +123,9 @@ static void print_address_cache(void)
}
}
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
+30 -25
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -61,9 +61,11 @@ static bool End_Of_File_Detected = false;
static bool Error_Detected = false;
static uint8_t Current_Invoke_ID = 0;
static void Atomic_Read_File_Error_Handler(BACNET_ADDRESS * src,
static void Atomic_Read_File_Error_Handler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void) src;
@@ -74,33 +76,38 @@ static void Atomic_Read_File_Error_Handler(BACNET_ADDRESS * src,
Error_Detected = true;
}
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason, bool server)
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
(void) server;
printf("\r\nBACnet Abort!\r\n");
printf("Abort Reason: %s\r\n",
bactext_abort_reason_name(abort_reason));
printf("Abort Reason: %s\r\n", bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("\r\nBACnet Reject!\r\n");
printf("Reject Reason: %s\r\n",
bactext_reject_reason_name(reject_reason));
printf("Reject Reason: %s\r\n", bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
static void LocalIAmHandler(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
static void LocalIAmHandler(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src)
{
int len = 0;
uint32_t device_id = 0;
@@ -120,15 +127,14 @@ static void LocalIAmHandler(uint8_t * service_request,
return;
}
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
LocalIAmHandler);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, LocalIAmHandler);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
@@ -143,7 +149,9 @@ static void Init_Service_Handlers(void)
apdu_set_reject_handler(MyRejectHandler);
}
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
@@ -193,8 +201,7 @@ int main(int argc, char *argv[])
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
@@ -209,8 +216,7 @@ int main(int argc, char *argv[])
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds -
last_seconds) * 1000));
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
if (End_Of_File_Detected || Error_Detected) {
printf("\r\n");
break;
@@ -258,8 +264,7 @@ int main(int argc, char *argv[])
invoke_id =
Send_Atomic_Write_File_Stream
(Target_Device_Object_Instance,
Target_File_Object_Instance, fileStartPosition,
&fileData);
Target_File_Object_Instance, fileStartPosition, &fileData);
Current_Invoke_ID = invoke_id;
} else if (tsm_invoke_id_failed(invoke_id)) {
fprintf(stderr, "\rError: TSM Timeout!\r\n");
+30 -27
View File
@@ -28,10 +28,10 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <string.h>
#include <errno.h>
#include <ctype.h> /* toupper */
#include <ctype.h> /* toupper */
#include "bactext.h"
#include "iam.h"
#include "arf.h"
@@ -71,9 +71,11 @@ static uint8_t Target_Object_Property_Priority = 0;
static BACNET_ADDRESS Target_Address;
static bool Error_Detected = false;
static void MyErrorHandler(BACNET_ADDRESS * src,
static void MyErrorHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void) src;
@@ -84,32 +86,36 @@ static void MyErrorHandler(BACNET_ADDRESS * src,
Error_Detected = true;
}
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason, bool server)
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
(void) server;
printf("\r\nBACnet Abort!\r\n");
printf("Abort Reason: %s\r\n",
bactext_abort_reason_name(abort_reason));
printf("Abort Reason: %s\r\n", bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("\r\nBACnet Reject!\r\n");
printf("Reject Reason: %s\r\n",
bactext_reject_reason_name(reject_reason));
printf("Reject Reason: %s\r\n", bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
void MyWritePropertySimpleAckHandler(BACNET_ADDRESS * src,
void MyWritePropertySimpleAckHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id)
{
(void) src;
@@ -117,15 +123,14 @@ void MyWritePropertySimpleAckHandler(BACNET_ADDRESS * src,
printf("\r\nWriteProperty Acknowledged!\r\n");
}
static void Init_Service_Handlers(void)
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
handler_i_am_bind);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
@@ -137,13 +142,14 @@ static void Init_Service_Handlers(void)
apdu_set_confirmed_simple_ack_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
MyWritePropertySimpleAckHandler);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
MyErrorHandler);
apdu_set_error_handler(SERVICE_CONFIRMED_WRITE_PROPERTY, MyErrorHandler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
int main(int argc, char *argv[])
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = { 0 }; /* address where message came from */
uint16_t pdu_len = 0;
@@ -234,8 +240,7 @@ int main(int argc, char *argv[])
"%s 123 1 0 85 4 100\r\n"
"You could also send a relinquish command:\r\n"
"%s 123 1 0 85 0 0\r\n",
filename_remove_path(argv[0]),
filename_remove_path(argv[0]));
filename_remove_path(argv[0]), filename_remove_path(argv[0]));
}
return 0;
}
@@ -317,8 +322,7 @@ int main(int argc, char *argv[])
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
@@ -333,8 +337,7 @@ int main(int argc, char *argv[])
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds -
last_seconds) * 1000));
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
if (Error_Detected)
break;
/* wait until the device is bound, or timeout and quit */