Indented.
This commit is contained in:
@@ -28,7 +28,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "iam.h"
|
#include "iam.h"
|
||||||
@@ -63,9 +63,11 @@ static char *Communication_Password = NULL;
|
|||||||
|
|
||||||
static bool Error_Detected = false;
|
static bool Error_Detected = false;
|
||||||
|
|
||||||
static void MyErrorHandler(BACNET_ADDRESS * src,
|
static void MyErrorHandler(
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
uint8_t invoke_id,
|
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 */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
@@ -76,30 +78,34 @@ static void MyErrorHandler(BACNET_ADDRESS * src,
|
|||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAbortHandler(BACNET_ADDRESS * src,
|
void MyAbortHandler(
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t abort_reason,
|
||||||
|
bool server)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
(void) server;
|
(void) server;
|
||||||
printf("BACnet Abort: %s\r\n",
|
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason));
|
||||||
bactext_abort_reason_name(abort_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyRejectHandler(BACNET_ADDRESS * src,
|
void MyRejectHandler(
|
||||||
uint8_t invoke_id, uint8_t reject_reason)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t reject_reason)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
printf("BACnet Reject: %s\r\n",
|
printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason));
|
||||||
bactext_reject_reason_name(reject_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyDeviceCommunicationControlSimpleAckHandler(BACNET_ADDRESS * src,
|
void MyDeviceCommunicationControlSimpleAckHandler(
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
uint8_t invoke_id)
|
uint8_t invoke_id)
|
||||||
{
|
{
|
||||||
(void) src;
|
(void) src;
|
||||||
@@ -107,15 +113,14 @@ void MyDeviceCommunicationControlSimpleAckHandler(BACNET_ADDRESS * src,
|
|||||||
printf("DeviceCommunicationControl Acknowledged!\r\n");
|
printf("DeviceCommunicationControl Acknowledged!\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Init_Service_Handlers(void)
|
static void Init_Service_Handlers(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
/* we need to handle who-is
|
/* we need to handle who-is
|
||||||
to support dynamic device binding to us */
|
to support dynamic device binding to us */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||||
handler_who_is);
|
|
||||||
/* handle i-am to support binding to other devices */
|
/* handle i-am to support binding to other devices */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
|
||||||
handler_i_am_bind);
|
|
||||||
/* set the handler for all the services we don't implement
|
/* set the handler for all the services we don't implement
|
||||||
It is required to send the proper reject message... */
|
It is required to send the proper reject message... */
|
||||||
apdu_set_unrecognized_service_handler_handler
|
apdu_set_unrecognized_service_handler_handler
|
||||||
@@ -138,7 +143,9 @@ static void Init_Service_Handlers(void)
|
|||||||
apdu_set_reject_handler(MyRejectHandler);
|
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 */
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
@@ -192,8 +199,7 @@ int main(int argc, char *argv[])
|
|||||||
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
||||||
Device_Number_Of_APDU_Retries();
|
Device_Number_Of_APDU_Retries();
|
||||||
/* try to bind with the device */
|
/* try to bind with the device */
|
||||||
Send_WhoIs(Target_Device_Object_Instance,
|
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
|
||||||
Target_Device_Object_Instance);
|
|
||||||
/* loop forever */
|
/* loop forever */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* increment timer - exit if timed out */
|
/* increment timer - exit if timed out */
|
||||||
@@ -208,8 +214,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
/* at least one second has passed */
|
/* at least one second has passed */
|
||||||
if (current_seconds != last_seconds)
|
if (current_seconds != last_seconds)
|
||||||
tsm_timer_milliseconds(((current_seconds -
|
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
|
||||||
last_seconds) * 1000));
|
|
||||||
if (Error_Detected)
|
if (Error_Detected)
|
||||||
break;
|
break;
|
||||||
/* wait until the device is bound, or timeout and quit */
|
/* wait until the device is bound, or timeout and quit */
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "iam.h"
|
#include "iam.h"
|
||||||
@@ -69,56 +69,62 @@ static BACNET_RP_SERVICE_DATA Read_Property_Data;
|
|||||||
/* FIXME: keep the object list in here */
|
/* FIXME: keep the object list in here */
|
||||||
/* static OS_Keylist Object_List; */
|
/* static OS_Keylist Object_List; */
|
||||||
|
|
||||||
static void MyErrorHandler(BACNET_ADDRESS * src,
|
static void MyErrorHandler(
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
uint8_t invoke_id,
|
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 */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
#if 1
|
#if 1
|
||||||
printf("BACnet Error: %s: %s\r\n",
|
printf("BACnet Error: %s: %s\r\n",
|
||||||
bactext_error_class_name(error_class),
|
bactext_error_class_name(error_class),
|
||||||
bactext_error_code_name(error_code));
|
bactext_error_code_name(error_code));
|
||||||
#else
|
#else
|
||||||
(void) error_class;
|
(void) error_class;
|
||||||
(void) error_code;
|
(void) error_code;
|
||||||
#endif
|
#endif
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAbortHandler(BACNET_ADDRESS * src,
|
void MyAbortHandler(
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t abort_reason,
|
||||||
|
bool server)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
(void) server;
|
(void) server;
|
||||||
#if 1
|
#if 1
|
||||||
printf("BACnet Abort: %s\r\n",
|
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason));
|
||||||
bactext_abort_reason_name(abort_reason));
|
#else
|
||||||
#else
|
|
||||||
(void) abort_reason;
|
(void) abort_reason;
|
||||||
#endif
|
#endif
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyRejectHandler(BACNET_ADDRESS * src,
|
void MyRejectHandler(
|
||||||
uint8_t invoke_id, uint8_t reject_reason)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t reject_reason)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
#if 1
|
#if 1
|
||||||
printf("BACnet Reject: %s\r\n",
|
printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason));
|
||||||
bactext_reject_reason_name(reject_reason));
|
#else
|
||||||
#else
|
|
||||||
(void) reject_reason;
|
(void) reject_reason;
|
||||||
#endif
|
#endif
|
||||||
Error_Detected = true;
|
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 */
|
BACNET_APPLICATION_DATA_VALUE value; /* for decode value data */
|
||||||
int len = 0;
|
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,
|
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;
|
int len = 0;
|
||||||
BACNET_READ_PROPERTY_DATA data;
|
BACNET_READ_PROPERTY_DATA data;
|
||||||
|
|
||||||
(void) src;
|
(void) src;
|
||||||
len = rp_ack_decode_service_request(service_request,
|
len = rp_ack_decode_service_request(service_request, service_len, &data);
|
||||||
service_len, &data);
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
memmove(&Read_Property_Data.service_data, service_data, sizeof(data));
|
memmove(&Read_Property_Data.service_data, service_data, sizeof(data));
|
||||||
memmove(&Read_Property_Data.data, &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
|
/* we need to handle who-is
|
||||||
to support dynamic device binding to us */
|
to support dynamic device binding to us */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||||
handler_who_is);
|
|
||||||
/* handle i-am to support binding to other devices */
|
/* handle i-am to support binding to other devices */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
|
||||||
handler_i_am_bind);
|
|
||||||
/* set the handler for all the services we don't implement
|
/* set the handler for all the services we don't implement
|
||||||
It is required to send the proper reject message... */
|
It is required to send the proper reject message... */
|
||||||
apdu_set_unrecognized_service_handler_handler
|
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,
|
apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||||
MyReadPropertyAckHandler);
|
MyReadPropertyAckHandler);
|
||||||
/* handle any errors coming back */
|
/* handle any errors coming back */
|
||||||
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler);
|
||||||
MyErrorHandler);
|
|
||||||
apdu_set_abort_handler(MyAbortHandler);
|
apdu_set_abort_handler(MyAbortHandler);
|
||||||
apdu_set_reject_handler(MyRejectHandler);
|
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;
|
uint8_t invoke_id = 0;
|
||||||
static unsigned index = 0;
|
static unsigned index = 0;
|
||||||
@@ -226,12 +232,10 @@ static uint8_t Read_Properties(uint32_t device_instance)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pRequired[index] != -1) {
|
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,
|
invoke_id = Send_Read_Property_Request(device_instance,
|
||||||
OBJECT_DEVICE,
|
OBJECT_DEVICE,
|
||||||
device_instance,
|
device_instance, pRequired[index], BACNET_ARRAY_ALL);
|
||||||
pRequired[index],
|
|
||||||
BACNET_ARRAY_ALL);
|
|
||||||
if (invoke_id) {
|
if (invoke_id) {
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
@@ -240,7 +244,9 @@ static uint8_t Read_Properties(uint32_t device_instance)
|
|||||||
return invoke_id;
|
return invoke_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(
|
||||||
|
int argc,
|
||||||
|
char *argv[])
|
||||||
{
|
{
|
||||||
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
@@ -257,9 +263,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
/* print help if not enough arguments */
|
/* print help if not enough arguments */
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
printf
|
printf("%s device-instance\r\n", filename_remove_path(argv[0]));
|
||||||
("%s device-instance\r\n",
|
|
||||||
filename_remove_path(argv[0]));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,7 +271,7 @@ int main(int argc, char *argv[])
|
|||||||
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
|
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
|
||||||
if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
|
if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
|
||||||
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
/* setup my info */
|
/* setup my info */
|
||||||
@@ -281,8 +285,7 @@ int main(int argc, char *argv[])
|
|||||||
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
||||||
Device_Number_Of_APDU_Retries();
|
Device_Number_Of_APDU_Retries();
|
||||||
/* try to bind with the device */
|
/* try to bind with the device */
|
||||||
Send_WhoIs(Target_Device_Object_Instance,
|
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
|
||||||
Target_Device_Object_Instance);
|
|
||||||
printf("List of Objects in test device:\r\n");
|
printf("List of Objects in test device:\r\n");
|
||||||
printf("{\r\n");
|
printf("{\r\n");
|
||||||
/* loop forever */
|
/* loop forever */
|
||||||
@@ -299,8 +302,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
/* at least one second has passed */
|
/* at least one second has passed */
|
||||||
if (current_seconds != last_seconds) {
|
if (current_seconds != last_seconds) {
|
||||||
tsm_timer_milliseconds(((current_seconds -
|
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
|
||||||
last_seconds) * 1000));
|
|
||||||
}
|
}
|
||||||
/* wait until the device is bound, or timeout and quit */
|
/* wait until the device is bound, or timeout and quit */
|
||||||
found = address_bind_request(Target_Device_Object_Instance,
|
found = address_bind_request(Target_Device_Object_Instance,
|
||||||
@@ -308,7 +310,7 @@ int main(int argc, char *argv[])
|
|||||||
if (found) {
|
if (found) {
|
||||||
/* invoke ID is set to zero when it is not in use */
|
/* invoke ID is set to zero when it is not in use */
|
||||||
if (invoke_id == 0) {
|
if (invoke_id == 0) {
|
||||||
invoke_id = Read_Properties(Target_Device_Object_Instance);
|
invoke_id = Read_Properties(Target_Device_Object_Instance);
|
||||||
if (invoke_id == 0) {
|
if (invoke_id == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -321,8 +323,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
} else if (tsm_invoke_id_free(invoke_id)) {
|
} else if (tsm_invoke_id_free(invoke_id)) {
|
||||||
invoke_id = 0;
|
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");
|
fprintf(stderr, "\rError: TSM Timeout!\r\n");
|
||||||
tsm_free_invoke_id(invoke_id);
|
tsm_free_invoke_id(invoke_id);
|
||||||
invoke_id = 0;
|
invoke_id = 0;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
#include "ai.h"
|
#include "ai.h"
|
||||||
#include "ao.h"
|
#include "ao.h"
|
||||||
#if defined(BACFILE)
|
#if defined(BACFILE)
|
||||||
#include "bacfile.h"
|
#include "bacfile.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -95,9 +95,11 @@ shall be TRUE, otherwise FALSE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(BACFILE)
|
#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,
|
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;
|
BACNET_ATOMIC_READ_FILE_DATA data;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -125,7 +127,7 @@ void handler_atomic_read_file(uint8_t * service_request,
|
|||||||
fprintf(stderr, "ARF: Segmented Message. Sending Abort!\n");
|
fprintf(stderr, "ARF: Segmented Message. Sending Abort!\n");
|
||||||
#endif
|
#endif
|
||||||
goto ARF_ABORT;
|
goto ARF_ABORT;
|
||||||
}
|
}
|
||||||
len = arf_decode_service_request(service_request, service_len, &data);
|
len = arf_decode_service_request(service_request, service_len, &data);
|
||||||
/* bad decoding - send an abort */
|
/* bad decoding - send an abort */
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
@@ -186,7 +188,7 @@ void handler_atomic_read_file(uint8_t * service_request,
|
|||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
SERVICE_CONFIRMED_ATOMIC_READ_FILE, error_class, error_code);
|
SERVICE_CONFIRMED_ATOMIC_READ_FILE, error_class, error_code);
|
||||||
}
|
}
|
||||||
ARF_ABORT:
|
ARF_ABORT:
|
||||||
pdu_len += len;
|
pdu_len += len;
|
||||||
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
||||||
&Handler_Transmit_Buffer[0], pdu_len);
|
&Handler_Transmit_Buffer[0], pdu_len);
|
||||||
|
|||||||
@@ -47,9 +47,11 @@
|
|||||||
/* that someone can read from us. It is common to */
|
/* that someone can read from us. It is common to */
|
||||||
/* use the description as the file name. */
|
/* use the description as the file name. */
|
||||||
#if defined(BACFILE)
|
#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,
|
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;
|
int len = 0;
|
||||||
BACNET_ATOMIC_READ_FILE_DATA data;
|
BACNET_ATOMIC_READ_FILE_DATA data;
|
||||||
@@ -60,8 +62,7 @@ void handler_atomic_read_file_ack(uint8_t * service_request,
|
|||||||
(void) src;
|
(void) src;
|
||||||
/* get the file instance from the tsm data before freeing it */
|
/* get the file instance from the tsm data before freeing it */
|
||||||
instance = bacfile_instance_from_tsm(service_data->invoke_id);
|
instance = bacfile_instance_from_tsm(service_data->invoke_id);
|
||||||
len = arf_ack_decode_service_request(service_request,
|
len = arf_ack_decode_service_request(service_request, service_len, &data);
|
||||||
service_len, &data);
|
|
||||||
#if PRINT_ENABLED
|
#if PRINT_ENABLED
|
||||||
fprintf(stderr, "Received Read-File Ack!\n");
|
fprintf(stderr, "Received Read-File Ack!\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
/* demo objects */
|
/* demo objects */
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#if defined(BACFILE)
|
#if defined(BACFILE)
|
||||||
#include "bacfile.h"
|
#include "bacfile.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -73,9 +73,11 @@ standard.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(BACFILE)
|
#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,
|
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;
|
BACNET_ATOMIC_WRITE_FILE_DATA data;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -113,7 +115,7 @@ void handler_atomic_write_file(uint8_t * service_request,
|
|||||||
fprintf(stderr, "Bad Encoding. Sending Abort!\n");
|
fprintf(stderr, "Bad Encoding. Sending Abort!\n");
|
||||||
#endif
|
#endif
|
||||||
goto AWF_ABORT;
|
goto AWF_ABORT;
|
||||||
}
|
}
|
||||||
if (data.object_type == OBJECT_FILE) {
|
if (data.object_type == OBJECT_FILE) {
|
||||||
if (!bacfile_valid_instance(data.object_instance)) {
|
if (!bacfile_valid_instance(data.object_instance)) {
|
||||||
error = true;
|
error = true;
|
||||||
@@ -126,7 +128,7 @@ void handler_atomic_write_file(uint8_t * service_request,
|
|||||||
#endif
|
#endif
|
||||||
len =
|
len =
|
||||||
awf_ack_encode_apdu(&Handler_Transmit_Buffer
|
awf_ack_encode_apdu(&Handler_Transmit_Buffer
|
||||||
[pdu_len], service_data->invoke_id, &data);
|
[pdu_len], service_data->invoke_id, &data);
|
||||||
} else {
|
} else {
|
||||||
error = true;
|
error = true;
|
||||||
error_class = ERROR_CLASS_OBJECT;
|
error_class = ERROR_CLASS_OBJECT;
|
||||||
@@ -151,7 +153,7 @@ void handler_atomic_write_file(uint8_t * service_request,
|
|||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
SERVICE_CONFIRMED_ATOMIC_READ_FILE, error_class, error_code);
|
SERVICE_CONFIRMED_ATOMIC_READ_FILE, error_class, error_code);
|
||||||
}
|
}
|
||||||
AWF_ABORT:
|
AWF_ABORT:
|
||||||
pdu_len += len;
|
pdu_len += len;
|
||||||
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
||||||
&Handler_Transmit_Buffer[0], pdu_len);
|
&Handler_Transmit_Buffer[0], pdu_len);
|
||||||
|
|||||||
@@ -40,9 +40,11 @@
|
|||||||
|
|
||||||
static char *My_Password = "filister";
|
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,
|
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;
|
uint16_t timeDuration = 0;
|
||||||
BACNET_COMMUNICATION_ENABLE_DISABLE state = COMMUNICATION_ENABLE;
|
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");
|
"Sending Abort - segmented message.\n");
|
||||||
#endif
|
#endif
|
||||||
goto DCC_ABORT;
|
goto DCC_ABORT;
|
||||||
}
|
}
|
||||||
/* decode the service request only */
|
/* decode the service request only */
|
||||||
len = dcc_decode_service_request(service_request,
|
len = dcc_decode_service_request(service_request,
|
||||||
service_len, &timeDuration, &state, &password);
|
service_len, &timeDuration, &state, &password);
|
||||||
@@ -121,7 +123,7 @@ void handler_device_communication_control(uint8_t * service_request,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DCC_ABORT:
|
DCC_ABORT:
|
||||||
pdu_len += len;
|
pdu_len += len;
|
||||||
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
||||||
&Handler_Transmit_Buffer[0], pdu_len);
|
&Handler_Transmit_Buffer[0], pdu_len);
|
||||||
|
|||||||
@@ -32,8 +32,10 @@
|
|||||||
#include "iam.h"
|
#include "iam.h"
|
||||||
#include "address.h"
|
#include "address.h"
|
||||||
|
|
||||||
void handler_i_am_add(uint8_t * service_request,
|
void handler_i_am_add(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src)
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
uint32_t device_id = 0;
|
uint32_t device_id = 0;
|
||||||
@@ -61,8 +63,10 @@ void handler_i_am_add(uint8_t * service_request,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handler_i_am_bind(uint8_t * service_request,
|
void handler_i_am_bind(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src)
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
uint32_t device_id = 0;
|
uint32_t device_id = 0;
|
||||||
|
|||||||
@@ -32,16 +32,17 @@
|
|||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "ihave.h"
|
#include "ihave.h"
|
||||||
|
|
||||||
void handler_i_have(uint8_t * service_request,
|
void handler_i_have(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src)
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
BACNET_I_HAVE_DATA data;
|
BACNET_I_HAVE_DATA data;
|
||||||
|
|
||||||
(void) service_len;
|
(void) service_len;
|
||||||
(void) src;
|
(void) src;
|
||||||
len = ihave_decode_service_request(service_request,
|
len = ihave_decode_service_request(service_request, service_len, &data);
|
||||||
service_len, &data);
|
|
||||||
if (len != -1) {
|
if (len != -1) {
|
||||||
#if PRINT_ENABLED
|
#if PRINT_ENABLED
|
||||||
fprintf(stderr, "I-Have: %s %d from %s %u!\r\n",
|
fprintf(stderr, "I-Have: %s %d from %s %u!\r\n",
|
||||||
|
|||||||
@@ -41,9 +41,11 @@
|
|||||||
static char *Password = "Jesus";
|
static char *Password = "Jesus";
|
||||||
static BACNET_CHARACTER_STRING My_Password;
|
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,
|
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_REINITIALIZED_STATE state;
|
||||||
BACNET_CHARACTER_STRING their_password;
|
BACNET_CHARACTER_STRING their_password;
|
||||||
@@ -70,7 +72,7 @@ void handler_reinitialize_device(uint8_t * service_request,
|
|||||||
"ReinitializeDevice: Sending Abort - segmented message.\n");
|
"ReinitializeDevice: Sending Abort - segmented message.\n");
|
||||||
#endif
|
#endif
|
||||||
goto RD_ABORT;
|
goto RD_ABORT;
|
||||||
}
|
}
|
||||||
/* decode the service request only */
|
/* decode the service request only */
|
||||||
len = rd_decode_service_request(service_request,
|
len = rd_decode_service_request(service_request,
|
||||||
service_len, &state, &their_password);
|
service_len, &state, &their_password);
|
||||||
@@ -124,7 +126,7 @@ void handler_reinitialize_device(uint8_t * service_request,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RD_ABORT:
|
RD_ABORT:
|
||||||
pdu_len += len;
|
pdu_len += len;
|
||||||
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
||||||
&Handler_Transmit_Buffer[0], pdu_len);
|
&Handler_Transmit_Buffer[0], pdu_len);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
#include "lsp.h"
|
#include "lsp.h"
|
||||||
#include "mso.h"
|
#include "mso.h"
|
||||||
#if defined(BACFILE)
|
#if defined(BACFILE)
|
||||||
#include "bacfile.h"
|
#include "bacfile.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
|
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
|
||||||
@@ -69,115 +69,82 @@ int Encode_Property_APDU(
|
|||||||
*error_class = ERROR_CLASS_OBJECT;
|
*error_class = ERROR_CLASS_OBJECT;
|
||||||
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||||
/* handle each object type */
|
/* handle each object type */
|
||||||
switch(object_type) {
|
switch (object_type) {
|
||||||
case OBJECT_DEVICE:
|
case OBJECT_DEVICE:
|
||||||
if (Device_Valid_Object_Instance_Number(object_instance)) {
|
if (Device_Valid_Object_Instance_Number(object_instance)) {
|
||||||
apdu_len = Device_Encode_Property_APDU(
|
apdu_len = Device_Encode_Property_APDU(&apdu[0],
|
||||||
&apdu[0],
|
property, array_index, error_class, error_code);
|
||||||
property,
|
|
||||||
array_index,
|
|
||||||
error_class, error_code);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OBJECT_ANALOG_INPUT:
|
case OBJECT_ANALOG_INPUT:
|
||||||
if (Analog_Input_Valid_Instance(object_instance)) {
|
if (Analog_Input_Valid_Instance(object_instance)) {
|
||||||
apdu_len = Analog_Input_Encode_Property_APDU(
|
apdu_len = Analog_Input_Encode_Property_APDU(&apdu[0],
|
||||||
&apdu[0],
|
|
||||||
object_instance,
|
object_instance,
|
||||||
property,
|
property, array_index, error_class, error_code);
|
||||||
array_index,
|
|
||||||
error_class, error_code);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OBJECT_ANALOG_OUTPUT:
|
case OBJECT_ANALOG_OUTPUT:
|
||||||
if (Analog_Output_Valid_Instance(object_instance)) {
|
if (Analog_Output_Valid_Instance(object_instance)) {
|
||||||
apdu_len = Analog_Output_Encode_Property_APDU(
|
apdu_len = Analog_Output_Encode_Property_APDU(&apdu[0],
|
||||||
&apdu[0],
|
|
||||||
object_instance,
|
object_instance,
|
||||||
property,
|
property, array_index, error_class, error_code);
|
||||||
array_index,
|
|
||||||
error_class, error_code);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OBJECT_ANALOG_VALUE:
|
case OBJECT_ANALOG_VALUE:
|
||||||
if (Analog_Value_Valid_Instance(object_instance)) {
|
if (Analog_Value_Valid_Instance(object_instance)) {
|
||||||
apdu_len = Analog_Value_Encode_Property_APDU(
|
apdu_len = Analog_Value_Encode_Property_APDU(&apdu[0],
|
||||||
&apdu[0],
|
|
||||||
object_instance,
|
object_instance,
|
||||||
property,
|
property, array_index, error_class, error_code);
|
||||||
array_index,
|
|
||||||
error_class, error_code);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OBJECT_BINARY_INPUT:
|
case OBJECT_BINARY_INPUT:
|
||||||
if (Binary_Input_Valid_Instance(object_instance)) {
|
if (Binary_Input_Valid_Instance(object_instance)) {
|
||||||
apdu_len = Binary_Input_Encode_Property_APDU(
|
apdu_len = Binary_Input_Encode_Property_APDU(&apdu[0],
|
||||||
&apdu[0],
|
|
||||||
object_instance,
|
object_instance,
|
||||||
property,
|
property, array_index, error_class, error_code);
|
||||||
array_index,
|
|
||||||
error_class, error_code);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OBJECT_BINARY_OUTPUT:
|
case OBJECT_BINARY_OUTPUT:
|
||||||
if (Binary_Output_Valid_Instance(object_instance)) {
|
if (Binary_Output_Valid_Instance(object_instance)) {
|
||||||
apdu_len = Binary_Output_Encode_Property_APDU(
|
apdu_len = Binary_Output_Encode_Property_APDU(&apdu[0],
|
||||||
&apdu[0],
|
|
||||||
object_instance,
|
object_instance,
|
||||||
property,
|
property, array_index, error_class, error_code);
|
||||||
array_index,
|
|
||||||
error_class, error_code);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OBJECT_BINARY_VALUE:
|
case OBJECT_BINARY_VALUE:
|
||||||
if (Binary_Value_Valid_Instance(object_instance)) {
|
if (Binary_Value_Valid_Instance(object_instance)) {
|
||||||
apdu_len = Binary_Value_Encode_Property_APDU(
|
apdu_len = Binary_Value_Encode_Property_APDU(&apdu[0],
|
||||||
&apdu[0],
|
|
||||||
object_instance,
|
object_instance,
|
||||||
property,
|
property, array_index, error_class, error_code);
|
||||||
array_index,
|
|
||||||
error_class, error_code);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OBJECT_LIFE_SAFETY_POINT:
|
case OBJECT_LIFE_SAFETY_POINT:
|
||||||
if (Life_Safety_Point_Valid_Instance(object_instance)) {
|
if (Life_Safety_Point_Valid_Instance(object_instance)) {
|
||||||
apdu_len = Life_Safety_Point_Encode_Property_APDU(
|
apdu_len = Life_Safety_Point_Encode_Property_APDU(&apdu[0],
|
||||||
&apdu[0],
|
|
||||||
object_instance,
|
object_instance,
|
||||||
property,
|
property, array_index, error_class, error_code);
|
||||||
array_index,
|
|
||||||
error_class, error_code);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OBJECT_LOAD_CONTROL:
|
case OBJECT_LOAD_CONTROL:
|
||||||
if (Load_Control_Valid_Instance(object_instance)) {
|
if (Load_Control_Valid_Instance(object_instance)) {
|
||||||
apdu_len = Load_Control_Encode_Property_APDU(
|
apdu_len = Load_Control_Encode_Property_APDU(&apdu[0],
|
||||||
&apdu[0],
|
|
||||||
object_instance,
|
object_instance,
|
||||||
property,
|
property, array_index, error_class, error_code);
|
||||||
array_index,
|
|
||||||
error_class, error_code);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OBJECT_MULTI_STATE_OUTPUT:
|
case OBJECT_MULTI_STATE_OUTPUT:
|
||||||
if (Multistate_Output_Valid_Instance(object_instance)) {
|
if (Multistate_Output_Valid_Instance(object_instance)) {
|
||||||
apdu_len = Multistate_Output_Encode_Property_APDU(
|
apdu_len = Multistate_Output_Encode_Property_APDU(&apdu[0],
|
||||||
&apdu[0],
|
|
||||||
object_instance,
|
object_instance,
|
||||||
property,
|
property, array_index, error_class, error_code);
|
||||||
array_index,
|
|
||||||
error_class, error_code);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#if defined(BACFILE)
|
#if defined(BACFILE)
|
||||||
case OBJECT_FILE:
|
case OBJECT_FILE:
|
||||||
if (bacfile_valid_instance(object_instance)) {
|
if (bacfile_valid_instance(object_instance)) {
|
||||||
apdu_len = bacfile_encode_property_apdu(
|
apdu_len = bacfile_encode_property_apdu(&apdu[0],
|
||||||
&apdu[0],
|
|
||||||
object_instance,
|
object_instance,
|
||||||
property,
|
property, array_index, error_class, error_code);
|
||||||
array_index,
|
|
||||||
error_class, error_code);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -190,9 +157,11 @@ int Encode_Property_APDU(
|
|||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handler_read_property(uint8_t * service_request,
|
void handler_read_property(
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
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;
|
BACNET_READ_PROPERTY_DATA data;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -237,13 +206,10 @@ void handler_read_property(uint8_t * service_request,
|
|||||||
|
|
||||||
/* assume that there is an error */
|
/* assume that there is an error */
|
||||||
error = true;
|
error = true;
|
||||||
len = Encode_Property_APDU(
|
len = Encode_Property_APDU(&Temp_Buf[0],
|
||||||
&Temp_Buf[0],
|
|
||||||
data.object_type,
|
data.object_type,
|
||||||
data.object_instance,
|
data.object_instance,
|
||||||
data.object_property,
|
data.object_property, data.array_index, &error_class, &error_code);
|
||||||
data.array_index,
|
|
||||||
&error_class, &error_code);
|
|
||||||
if (len >= 0) {
|
if (len >= 0) {
|
||||||
/* encode the APDU portion of the packet */
|
/* encode the APDU portion of the packet */
|
||||||
data.application_data = &Temp_Buf[0];
|
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],
|
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||||
service_data->invoke_id, &data);
|
service_data->invoke_id, &data);
|
||||||
#if PRINT_ENABLED
|
#if PRINT_ENABLED
|
||||||
fprintf(stderr,
|
fprintf(stderr, "RP: Sending Ack!\n");
|
||||||
"RP: Sending Ack!\n");
|
|
||||||
#endif
|
#endif
|
||||||
error = false;
|
error = false;
|
||||||
}
|
}
|
||||||
@@ -276,7 +241,7 @@ void handler_read_property(uint8_t * service_request,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RP_ABORT:
|
RP_ABORT:
|
||||||
pdu_len += len;
|
pdu_len += len;
|
||||||
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
||||||
&Handler_Transmit_Buffer[0], pdu_len);
|
&Handler_Transmit_Buffer[0], pdu_len);
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
|
||||||
/* for debugging... */
|
/* 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 */
|
BACNET_APPLICATION_DATA_VALUE value; /* for decode value data */
|
||||||
int len = 0;
|
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,
|
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;
|
int len = 0;
|
||||||
BACNET_READ_PROPERTY_DATA data;
|
BACNET_READ_PROPERTY_DATA data;
|
||||||
|
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) service_data; /* we could use these... */
|
(void) service_data; /* we could use these... */
|
||||||
len = rp_ack_decode_service_request(service_request,
|
len = rp_ack_decode_service_request(service_request, service_len, &data);
|
||||||
service_len, &data);
|
|
||||||
#if 0
|
#if 0
|
||||||
fprintf(stderr, "Received Read-Property Ack!\n");
|
fprintf(stderr, "Received Read-Property Ack!\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+143
-190
@@ -49,25 +49,24 @@
|
|||||||
#include "lsp.h"
|
#include "lsp.h"
|
||||||
#include "mso.h"
|
#include "mso.h"
|
||||||
#if defined(BACFILE)
|
#if defined(BACFILE)
|
||||||
#include "bacfile.h"
|
#include "bacfile.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
|
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
|
||||||
|
|
||||||
struct property_list_t
|
struct property_list_t {
|
||||||
{
|
|
||||||
const int *pList;
|
const int *pList;
|
||||||
unsigned count;
|
unsigned count;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct special_property_list_t
|
struct special_property_list_t {
|
||||||
{
|
|
||||||
struct property_list_t Required;
|
struct property_list_t Required;
|
||||||
struct property_list_t Optional;
|
struct property_list_t Optional;
|
||||||
struct property_list_t Proprietary;
|
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;
|
unsigned property_count = 0;
|
||||||
|
|
||||||
@@ -90,72 +89,62 @@ static void RPM_Property_List(
|
|||||||
pPropertyList->Optional.pList = NULL;
|
pPropertyList->Optional.pList = NULL;
|
||||||
pPropertyList->Proprietary.pList = NULL;
|
pPropertyList->Proprietary.pList = NULL;
|
||||||
switch (object_type) {
|
switch (object_type) {
|
||||||
case OBJECT_ANALOG_INPUT:
|
case OBJECT_ANALOG_INPUT:
|
||||||
Analog_Input_Property_Lists(
|
Analog_Input_Property_Lists(&pPropertyList->Required.pList,
|
||||||
&pPropertyList->Required.pList,
|
&pPropertyList->Optional.pList,
|
||||||
&pPropertyList->Optional.pList,
|
&pPropertyList->Proprietary.pList);
|
||||||
&pPropertyList->Proprietary.pList);
|
break;
|
||||||
break;
|
case OBJECT_ANALOG_OUTPUT:
|
||||||
case OBJECT_ANALOG_OUTPUT:
|
Analog_Output_Property_Lists(&pPropertyList->Required.pList,
|
||||||
Analog_Output_Property_Lists(
|
&pPropertyList->Optional.pList,
|
||||||
&pPropertyList->Required.pList,
|
&pPropertyList->Proprietary.pList);
|
||||||
&pPropertyList->Optional.pList,
|
break;
|
||||||
&pPropertyList->Proprietary.pList);
|
case OBJECT_ANALOG_VALUE:
|
||||||
break;
|
Analog_Value_Property_Lists(&pPropertyList->Required.pList,
|
||||||
case OBJECT_ANALOG_VALUE:
|
&pPropertyList->Optional.pList,
|
||||||
Analog_Value_Property_Lists(
|
&pPropertyList->Proprietary.pList);
|
||||||
&pPropertyList->Required.pList,
|
break;
|
||||||
&pPropertyList->Optional.pList,
|
case OBJECT_BINARY_INPUT:
|
||||||
&pPropertyList->Proprietary.pList);
|
Binary_Input_Property_Lists(&pPropertyList->Required.pList,
|
||||||
break;
|
&pPropertyList->Optional.pList,
|
||||||
case OBJECT_BINARY_INPUT:
|
&pPropertyList->Proprietary.pList);
|
||||||
Binary_Input_Property_Lists(
|
break;
|
||||||
&pPropertyList->Required.pList,
|
case OBJECT_BINARY_OUTPUT:
|
||||||
&pPropertyList->Optional.pList,
|
Binary_Output_Property_Lists(&pPropertyList->Required.pList,
|
||||||
&pPropertyList->Proprietary.pList);
|
&pPropertyList->Optional.pList,
|
||||||
break;
|
&pPropertyList->Proprietary.pList);
|
||||||
case OBJECT_BINARY_OUTPUT:
|
break;
|
||||||
Binary_Output_Property_Lists(
|
case OBJECT_BINARY_VALUE:
|
||||||
&pPropertyList->Required.pList,
|
Binary_Value_Property_Lists(&pPropertyList->Required.pList,
|
||||||
&pPropertyList->Optional.pList,
|
&pPropertyList->Optional.pList,
|
||||||
&pPropertyList->Proprietary.pList);
|
&pPropertyList->Proprietary.pList);
|
||||||
break;
|
break;
|
||||||
case OBJECT_BINARY_VALUE:
|
case OBJECT_LIFE_SAFETY_POINT:
|
||||||
Binary_Value_Property_Lists(
|
Life_Safety_Point_Property_Lists(&pPropertyList->Required.pList,
|
||||||
&pPropertyList->Required.pList,
|
&pPropertyList->Optional.pList,
|
||||||
&pPropertyList->Optional.pList,
|
&pPropertyList->Proprietary.pList);
|
||||||
&pPropertyList->Proprietary.pList);
|
break;
|
||||||
break;
|
case OBJECT_LOAD_CONTROL:
|
||||||
case OBJECT_LIFE_SAFETY_POINT:
|
Load_Control_Property_Lists(&pPropertyList->Required.pList,
|
||||||
Life_Safety_Point_Property_Lists(
|
&pPropertyList->Optional.pList,
|
||||||
&pPropertyList->Required.pList,
|
&pPropertyList->Proprietary.pList);
|
||||||
&pPropertyList->Optional.pList,
|
break;
|
||||||
&pPropertyList->Proprietary.pList);
|
case OBJECT_MULTI_STATE_OUTPUT:
|
||||||
break;
|
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)
|
#if defined(BACFILE)
|
||||||
case OBJECT_FILE:
|
case OBJECT_FILE:
|
||||||
BACfile_Property_Lists(
|
BACfile_Property_Lists(&pPropertyList->Required.pList,
|
||||||
&pPropertyList->Required.pList,
|
&pPropertyList->Optional.pList,
|
||||||
&pPropertyList->Optional.pList,
|
&pPropertyList->Proprietary.pList);
|
||||||
&pPropertyList->Proprietary.pList);
|
break;
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
case OBJECT_DEVICE:
|
case OBJECT_DEVICE:
|
||||||
Device_Property_Lists(
|
Device_Property_Lists(&pPropertyList->Required.pList,
|
||||||
&pPropertyList->Required.pList,
|
&pPropertyList->Optional.pList,
|
||||||
&pPropertyList->Optional.pList,
|
&pPropertyList->Proprietary.pList);
|
||||||
&pPropertyList->Proprietary.pList);
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
/* fill the count */
|
/* fill the count */
|
||||||
pPropertyList->Required.count =
|
pPropertyList->Required.count =
|
||||||
@@ -173,7 +162,7 @@ static int RPM_Object_Property(
|
|||||||
BACNET_PROPERTY_ID special_property,
|
BACNET_PROPERTY_ID special_property,
|
||||||
unsigned index)
|
unsigned index)
|
||||||
{
|
{
|
||||||
int property = -1; /* return value */
|
int property = -1; /* return value */
|
||||||
unsigned required, optional, proprietary;
|
unsigned required, optional, proprietary;
|
||||||
|
|
||||||
required = pPropertyList->Required.count;
|
required = pPropertyList->Required.count;
|
||||||
@@ -210,8 +199,7 @@ static unsigned RPM_Object_Property_Count(
|
|||||||
|
|
||||||
if (special_property == PROP_ALL) {
|
if (special_property == PROP_ALL) {
|
||||||
count = pPropertyList->Required.count +
|
count = pPropertyList->Required.count +
|
||||||
pPropertyList->Optional.count +
|
pPropertyList->Optional.count + pPropertyList->Proprietary.count;
|
||||||
pPropertyList->Proprietary.count;
|
|
||||||
} else if (special_property == PROP_REQUIRED) {
|
} else if (special_property == PROP_REQUIRED) {
|
||||||
count = pPropertyList->Required.count;
|
count = pPropertyList->Required.count;
|
||||||
} else if (special_property == PROP_OPTIONAL) {
|
} 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. */
|
/* 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 i;
|
||||||
int copy_len = 0;
|
int copy_len = 0;
|
||||||
|
|
||||||
if (len <= (max-offset)) {
|
if (len <= (max - offset)) {
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
dest[offset+i] = src[i];
|
dest[offset + i] = src[i];
|
||||||
copy_len++;
|
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,
|
/* Encode the RPM property returning the length of the encoding,
|
||||||
or 0 if there is no room to fit 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 offset,
|
||||||
uint16_t max_apdu,
|
uint16_t max_apdu,
|
||||||
BACNET_OBJECT_TYPE object_type,
|
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_CLASS error_class = ERROR_CLASS_OBJECT;
|
||||||
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||||
|
|
||||||
len = rpm_ack_encode_apdu_object_property(
|
len = rpm_ack_encode_apdu_object_property(&Temp_Buf[0],
|
||||||
&Temp_Buf[0],
|
object_property, array_index);
|
||||||
object_property,
|
|
||||||
array_index);
|
|
||||||
len = apdu_copy(&apdu[0], &Temp_Buf[0], offset, len, max_apdu);
|
len = apdu_copy(&apdu[0], &Temp_Buf[0], offset, len, max_apdu);
|
||||||
if (!len)
|
if (!len)
|
||||||
return 0;
|
return 0;
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
len = Encode_Property_APDU(
|
len = Encode_Property_APDU(&Temp_Buf[0],
|
||||||
&Temp_Buf[0],
|
|
||||||
object_type,
|
object_type,
|
||||||
object_instance,
|
object_instance,
|
||||||
object_property,
|
object_property, array_index, &error_class, &error_code);
|
||||||
array_index,
|
|
||||||
&error_class, &error_code);
|
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
/* error was returned - encode that for the response */
|
/* error was returned - encode that for the response */
|
||||||
len = rpm_ack_encode_apdu_object_property_error(
|
len = rpm_ack_encode_apdu_object_property_error(&Temp_Buf[0],
|
||||||
&Temp_Buf[0],
|
|
||||||
error_class, error_code);
|
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)
|
if (!len)
|
||||||
return 0;
|
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 */
|
/* enough room to fit the property value and tags */
|
||||||
len = rpm_ack_encode_apdu_object_property_value(
|
len =
|
||||||
&apdu[offset+apdu_len],
|
rpm_ack_encode_apdu_object_property_value(&apdu[offset + apdu_len],
|
||||||
&Temp_Buf[0],
|
&Temp_Buf[0], len);
|
||||||
len);
|
|
||||||
} else {
|
} else {
|
||||||
/* not enough room - abort! */
|
/* not enough room - abort! */
|
||||||
return 0;
|
return 0;
|
||||||
@@ -311,16 +300,14 @@ void handler_read_property_multiple(
|
|||||||
int32_t array_index = 0;
|
int32_t array_index = 0;
|
||||||
|
|
||||||
/* jps_debug - see if we are utilizing all the buffer */
|
/* 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 */
|
/* encode the NPDU portion of the packet */
|
||||||
datalink_get_my_address(&my_address);
|
datalink_get_my_address(&my_address);
|
||||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||||
npdu_len = npdu_encode_pdu(
|
npdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0],
|
||||||
&Handler_Transmit_Buffer[0],
|
|
||||||
src, &my_address, &npdu_data);
|
src, &my_address, &npdu_data);
|
||||||
if (service_data->segmented_message) {
|
if (service_data->segmented_message) {
|
||||||
apdu_len = abort_encode_apdu(
|
apdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
|
||||||
&Handler_Transmit_Buffer[npdu_len],
|
|
||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||||
#if PRINT_ENABLED
|
#if PRINT_ENABLED
|
||||||
@@ -330,102 +317,82 @@ void handler_read_property_multiple(
|
|||||||
}
|
}
|
||||||
/* decode apdu request & encode apdu reply
|
/* decode apdu request & encode apdu reply
|
||||||
encode complex ack, invoke id, service choice */
|
encode complex ack, invoke id, service choice */
|
||||||
apdu_len = rpm_ack_encode_apdu_init(
|
apdu_len = rpm_ack_encode_apdu_init(&Handler_Transmit_Buffer[npdu_len],
|
||||||
&Handler_Transmit_Buffer[npdu_len],
|
|
||||||
service_data->invoke_id);
|
service_data->invoke_id);
|
||||||
do
|
do {
|
||||||
{
|
len = rpm_decode_object_id(&service_request[decode_len],
|
||||||
len = rpm_decode_object_id(
|
service_len - decode_len, &object_type, &object_instance);
|
||||||
&service_request[decode_len],
|
|
||||||
service_len - decode_len,
|
|
||||||
&object_type, &object_instance);
|
|
||||||
/* end of object? */
|
/* end of object? */
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
decode_len += len;
|
decode_len += len;
|
||||||
} else {
|
} else {
|
||||||
len = rpm_decode_object_end(
|
len = rpm_decode_object_end(&service_request[decode_len],
|
||||||
&service_request[decode_len],
|
|
||||||
service_len - decode_len);
|
service_len - decode_len);
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
decode_len++;
|
decode_len++;
|
||||||
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
|
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
|
||||||
copy_len = apdu_copy(
|
copy_len =
|
||||||
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
|
apdu_copy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
|
||||||
apdu_len, len,
|
apdu_len, len, sizeof(Handler_Transmit_Buffer));
|
||||||
sizeof(Handler_Transmit_Buffer));
|
|
||||||
if (!copy_len) {
|
if (!copy_len) {
|
||||||
apdu_len = abort_encode_apdu(
|
apdu_len =
|
||||||
&Handler_Transmit_Buffer[npdu_len],
|
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
|
||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||||
true);
|
|
||||||
goto RPM_ABORT;
|
goto RPM_ABORT;
|
||||||
} else {
|
} else {
|
||||||
apdu_len += copy_len;
|
apdu_len += copy_len;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
apdu_len = abort_encode_apdu(
|
apdu_len =
|
||||||
&Handler_Transmit_Buffer[npdu_len],
|
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
|
||||||
service_data->invoke_id,
|
service_data->invoke_id, ABORT_REASON_OTHER, true);
|
||||||
ABORT_REASON_OTHER, true);
|
|
||||||
goto RPM_ABORT;
|
goto RPM_ABORT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
len = rpm_ack_encode_apdu_object_begin(
|
len = rpm_ack_encode_apdu_object_begin(&Temp_Buf[0],
|
||||||
&Temp_Buf[0],
|
|
||||||
object_type, object_instance);
|
object_type, object_instance);
|
||||||
copy_len = apdu_copy(
|
copy_len = apdu_copy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
|
||||||
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
|
apdu_len, len, sizeof(Handler_Transmit_Buffer));
|
||||||
apdu_len, len,
|
|
||||||
sizeof(Handler_Transmit_Buffer));
|
|
||||||
if (!copy_len) {
|
if (!copy_len) {
|
||||||
apdu_len = abort_encode_apdu(
|
apdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
|
||||||
&Handler_Transmit_Buffer[npdu_len],
|
|
||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||||
true);
|
|
||||||
goto RPM_ABORT;
|
goto RPM_ABORT;
|
||||||
} else {
|
} else {
|
||||||
apdu_len += copy_len;
|
apdu_len += copy_len;
|
||||||
}
|
}
|
||||||
/* do each property of this object of the RPM request */
|
/* do each property of this object of the RPM request */
|
||||||
do
|
do {
|
||||||
{
|
len = rpm_decode_object_property(&service_request[decode_len],
|
||||||
len = rpm_decode_object_property(
|
service_len - decode_len, &object_property, &array_index);
|
||||||
&service_request[decode_len],
|
|
||||||
service_len - decode_len,
|
|
||||||
&object_property,
|
|
||||||
&array_index);
|
|
||||||
/* end of property list? */
|
/* end of property list? */
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
decode_len += len;
|
decode_len += len;
|
||||||
} else {
|
} else {
|
||||||
len = rpm_decode_object_end(
|
len = rpm_decode_object_end(&service_request[decode_len],
|
||||||
&service_request[decode_len],
|
|
||||||
service_len - decode_len);
|
service_len - decode_len);
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
decode_len++;
|
decode_len++;
|
||||||
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
|
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
|
||||||
copy_len = apdu_copy(
|
copy_len =
|
||||||
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
|
apdu_copy(&Handler_Transmit_Buffer[npdu_len],
|
||||||
apdu_len, len,
|
&Temp_Buf[0], apdu_len, len,
|
||||||
sizeof(Handler_Transmit_Buffer));
|
sizeof(Handler_Transmit_Buffer));
|
||||||
if (!copy_len) {
|
if (!copy_len) {
|
||||||
apdu_len = abort_encode_apdu(
|
apdu_len =
|
||||||
&Handler_Transmit_Buffer[npdu_len],
|
abort_encode_apdu(&Handler_Transmit_Buffer
|
||||||
service_data->invoke_id,
|
[npdu_len], service_data->invoke_id,
|
||||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||||
true);
|
|
||||||
goto RPM_ABORT;
|
goto RPM_ABORT;
|
||||||
} else {
|
} else {
|
||||||
apdu_len += copy_len;
|
apdu_len += copy_len;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
apdu_len = abort_encode_apdu(
|
apdu_len =
|
||||||
&Handler_Transmit_Buffer[npdu_len],
|
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
|
||||||
service_data->invoke_id,
|
service_data->invoke_id, ABORT_REASON_OTHER, true);
|
||||||
ABORT_REASON_OTHER, true);
|
|
||||||
goto RPM_ABORT;
|
goto RPM_ABORT;
|
||||||
}
|
}
|
||||||
/* stop decoding properties */
|
/* stop decoding properties */
|
||||||
@@ -434,8 +401,7 @@ void handler_read_property_multiple(
|
|||||||
/* handle the special properties */
|
/* handle the special properties */
|
||||||
if ((object_property == PROP_ALL) ||
|
if ((object_property == PROP_ALL) ||
|
||||||
(object_property == PROP_REQUIRED) ||
|
(object_property == PROP_REQUIRED) ||
|
||||||
(object_property == PROP_OPTIONAL))
|
(object_property == PROP_OPTIONAL)) {
|
||||||
{
|
|
||||||
struct special_property_list_t property_list;
|
struct special_property_list_t property_list;
|
||||||
unsigned property_count = 0;
|
unsigned property_count = 0;
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
@@ -443,63 +409,50 @@ void handler_read_property_multiple(
|
|||||||
|
|
||||||
special_object_property = object_property;
|
special_object_property = object_property;
|
||||||
RPM_Property_List(object_type, &property_list);
|
RPM_Property_List(object_type, &property_list);
|
||||||
property_count = RPM_Object_Property_Count(
|
property_count = RPM_Object_Property_Count(&property_list,
|
||||||
&property_list,
|
|
||||||
special_object_property);
|
special_object_property);
|
||||||
for (index = 0; index < property_count; index++)
|
for (index = 0; index < property_count; index++) {
|
||||||
{
|
object_property = RPM_Object_Property(&property_list,
|
||||||
object_property = RPM_Object_Property(
|
special_object_property, index);
|
||||||
&property_list,
|
len = RPM_Encode_Property(&Handler_Transmit_Buffer[0],
|
||||||
special_object_property,
|
|
||||||
index);
|
|
||||||
len = RPM_Encode_Property(
|
|
||||||
&Handler_Transmit_Buffer[0],
|
|
||||||
npdu_len + apdu_len,
|
npdu_len + apdu_len,
|
||||||
sizeof(Handler_Transmit_Buffer),
|
sizeof(Handler_Transmit_Buffer),
|
||||||
object_type,
|
object_type,
|
||||||
object_instance,
|
object_instance, object_property, array_index);
|
||||||
object_property,
|
|
||||||
array_index);
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
} else {
|
} else {
|
||||||
apdu_len = abort_encode_apdu(
|
apdu_len =
|
||||||
&Handler_Transmit_Buffer[npdu_len],
|
abort_encode_apdu(&Handler_Transmit_Buffer
|
||||||
service_data->invoke_id,
|
[npdu_len], service_data->invoke_id,
|
||||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||||
goto RPM_ABORT;
|
goto RPM_ABORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* handle an individual property */
|
/* handle an individual property */
|
||||||
len = RPM_Encode_Property(
|
len = RPM_Encode_Property(&Handler_Transmit_Buffer[0],
|
||||||
&Handler_Transmit_Buffer[0],
|
|
||||||
npdu_len + apdu_len,
|
npdu_len + apdu_len,
|
||||||
sizeof(Handler_Transmit_Buffer),
|
sizeof(Handler_Transmit_Buffer),
|
||||||
object_type,
|
object_type,
|
||||||
object_instance,
|
object_instance, object_property, array_index);
|
||||||
object_property,
|
|
||||||
array_index);
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
} else {
|
} else {
|
||||||
apdu_len = abort_encode_apdu(
|
apdu_len =
|
||||||
&Handler_Transmit_Buffer[npdu_len],
|
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
|
||||||
service_data->invoke_id,
|
service_data->invoke_id,
|
||||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||||
goto RPM_ABORT;
|
goto RPM_ABORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while(1);
|
} while (1);
|
||||||
if (decode_len >= service_len) {
|
if (decode_len >= service_len) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while(1);
|
} while (1);
|
||||||
RPM_ABORT:
|
RPM_ABORT:
|
||||||
pdu_len = apdu_len + npdu_len;
|
pdu_len = apdu_len + npdu_len;
|
||||||
bytes_sent = datalink_send_pdu(
|
bytes_sent = datalink_send_pdu(src,
|
||||||
src,
|
&npdu_data, &Handler_Transmit_Buffer[0], pdu_len);
|
||||||
&npdu_data,
|
|
||||||
&Handler_Transmit_Buffer[0],
|
|
||||||
pdu_len);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,9 @@
|
|||||||
#include "timesync.h"
|
#include "timesync.h"
|
||||||
|
|
||||||
#if PRINT_ENABLED
|
#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 */
|
/* show the date received */
|
||||||
fprintf(stderr, "%u", (unsigned) bdate->year);
|
fprintf(stderr, "%u", (unsigned) bdate->year);
|
||||||
@@ -47,8 +49,10 @@ static void show_bacnet_date_time(BACNET_DATE * bdate, BACNET_TIME * btime)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void handler_timesync(uint8_t * service_request,
|
void handler_timesync(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src)
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
BACNET_DATE bdate;
|
BACNET_DATE bdate;
|
||||||
@@ -67,8 +71,10 @@ void handler_timesync(uint8_t * service_request,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handler_timesync_utc(uint8_t * service_request,
|
void handler_timesync_utc(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src)
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
BACNET_DATE bdate;
|
BACNET_DATE bdate;
|
||||||
@@ -86,4 +92,3 @@ void handler_timesync_utc(uint8_t * service_request,
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,10 @@
|
|||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
|
||||||
void handler_who_has(uint8_t * service_request,
|
void handler_who_has(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src)
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
BACNET_WHO_HAS_DATA data;
|
BACNET_WHO_HAS_DATA data;
|
||||||
@@ -47,15 +49,12 @@ void handler_who_has(uint8_t * service_request,
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
(void) src;
|
(void) src;
|
||||||
len = whohas_decode_service_request(service_request,
|
len = whohas_decode_service_request(service_request, service_len, &data);
|
||||||
service_len, &data);
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
if ((data.low_limit == -1) || (data.high_limit == -1))
|
if ((data.low_limit == -1) || (data.high_limit == -1))
|
||||||
directed_to_me = true;
|
directed_to_me = true;
|
||||||
else if ((Device_Object_Instance_Number() >=
|
else if ((Device_Object_Instance_Number() >= (uint32_t) data.low_limit)
|
||||||
(uint32_t) data.low_limit)
|
&& (Device_Object_Instance_Number() <= (uint32_t) data.high_limit))
|
||||||
&& (Device_Object_Instance_Number() <=
|
|
||||||
(uint32_t) data.high_limit))
|
|
||||||
directed_to_me = true;
|
directed_to_me = true;
|
||||||
if (directed_to_me) {
|
if (directed_to_me) {
|
||||||
/* do we have such an object? If so, send an I-Have.
|
/* do we have such an object? If so, send an I-Have.
|
||||||
|
|||||||
@@ -37,8 +37,10 @@
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
|
||||||
void handler_who_is(uint8_t * service_request,
|
void handler_who_is(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src)
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int32_t low_limit = 0;
|
int32_t low_limit = 0;
|
||||||
|
|||||||
+204
-231
@@ -47,12 +47,14 @@
|
|||||||
#include "lsp.h"
|
#include "lsp.h"
|
||||||
#include "mso.h"
|
#include "mso.h"
|
||||||
#if defined(BACFILE)
|
#if defined(BACFILE)
|
||||||
#include "bacfile.h"
|
#include "bacfile.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void handler_write_property(uint8_t * service_request,
|
void handler_write_property(
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
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;
|
BACNET_WRITE_PROPERTY_DATA wp_data;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -79,9 +81,8 @@ void handler_write_property(uint8_t * service_request,
|
|||||||
fprintf(stderr, "WP: Segmented message. Sending Abort!\n");
|
fprintf(stderr, "WP: Segmented message. Sending Abort!\n");
|
||||||
#endif
|
#endif
|
||||||
goto WP_ABORT;
|
goto WP_ABORT;
|
||||||
} /* decode the service request only */
|
} /* decode the service request only */
|
||||||
len = wp_decode_service_request(service_request,
|
len = wp_decode_service_request(service_request, service_len, &wp_data);
|
||||||
service_len, &wp_data);
|
|
||||||
#if PRINT_ENABLED
|
#if PRINT_ENABLED
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
fprintf(stderr, "WP: type=%u instance=%u property=%u index=%d\n",
|
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");
|
fprintf(stderr, "WP: Bad Encoding. Sending Abort!\n");
|
||||||
#endif
|
#endif
|
||||||
goto WP_ABORT;
|
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;
|
pdu_len += len;
|
||||||
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
bytes_sent = datalink_send_pdu(src, &npdu_data,
|
||||||
&Handler_Transmit_Buffer[0], pdu_len);
|
&Handler_Transmit_Buffer[0], pdu_len);
|
||||||
|
|||||||
@@ -34,9 +34,11 @@
|
|||||||
#include "npdu.h"
|
#include "npdu.h"
|
||||||
#include "reject.h"
|
#include "reject.h"
|
||||||
|
|
||||||
void handler_unrecognized_service(uint8_t * service_request,
|
void handler_unrecognized_service(
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
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 len = 0;
|
||||||
int pdu_len = 0;
|
int pdu_len = 0;
|
||||||
|
|||||||
@@ -42,9 +42,11 @@
|
|||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
#include "txbuf.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,
|
uint32_t file_instance,
|
||||||
int fileStartPosition, unsigned requestedOctetCount)
|
int fileStartPosition,
|
||||||
|
unsigned requestedOctetCount)
|
||||||
{
|
{
|
||||||
BACNET_ADDRESS dest;
|
BACNET_ADDRESS dest;
|
||||||
BACNET_ADDRESS my_address;
|
BACNET_ADDRESS my_address;
|
||||||
|
|||||||
@@ -42,9 +42,11 @@
|
|||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
#include "txbuf.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,
|
uint32_t file_instance,
|
||||||
int fileStartPosition, BACNET_OCTET_STRING * fileData)
|
int fileStartPosition,
|
||||||
|
BACNET_OCTET_STRING * fileData)
|
||||||
{
|
{
|
||||||
BACNET_ADDRESS dest;
|
BACNET_ADDRESS dest;
|
||||||
BACNET_ADDRESS my_address;
|
BACNET_ADDRESS my_address;
|
||||||
@@ -76,8 +78,7 @@ uint8_t Send_Atomic_Write_File_Stream(uint32_t device_id,
|
|||||||
if (status) {
|
if (status) {
|
||||||
/* encode the NPDU portion of the packet */
|
/* encode the NPDU portion of the packet */
|
||||||
datalink_get_my_address(&my_address);
|
datalink_get_my_address(&my_address);
|
||||||
npdu_encode_npdu_data(&npdu_data, true,
|
npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
|
||||||
MESSAGE_PRIORITY_NORMAL);
|
|
||||||
pdu_len =
|
pdu_len =
|
||||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest,
|
npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest,
|
||||||
&my_address, &npdu_data);
|
&my_address, &npdu_data);
|
||||||
@@ -116,8 +117,7 @@ uint8_t Send_Atomic_Write_File_Stream(uint32_t device_id,
|
|||||||
invoke_id = 0;
|
invoke_id = 0;
|
||||||
#if PRINT_ENABLED
|
#if PRINT_ENABLED
|
||||||
fprintf(stderr, "Failed to Send AtomicWriteFile Request "
|
fprintf(stderr, "Failed to Send AtomicWriteFile Request "
|
||||||
"(payload [%d] exceeds octet string capacity)!\n",
|
"(payload [%d] exceeds octet string capacity)!\n", pdu_len);
|
||||||
pdu_len);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,9 +42,12 @@
|
|||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
|
||||||
uint8_t Send_Device_Communication_Control_Request(uint32_t device_id, uint16_t timeDuration, /* 0=optional */
|
uint8_t Send_Device_Communication_Control_Request(
|
||||||
BACNET_COMMUNICATION_ENABLE_DISABLE state, char *password)
|
uint32_t device_id,
|
||||||
{ /* NULL=optional */
|
uint16_t timeDuration, /* 0=optional */
|
||||||
|
BACNET_COMMUNICATION_ENABLE_DISABLE state,
|
||||||
|
char *password)
|
||||||
|
{ /* NULL=optional */
|
||||||
BACNET_ADDRESS dest;
|
BACNET_ADDRESS dest;
|
||||||
BACNET_ADDRESS my_address;
|
BACNET_ADDRESS my_address;
|
||||||
unsigned max_apdu = 0;
|
unsigned max_apdu = 0;
|
||||||
|
|||||||
@@ -44,9 +44,11 @@
|
|||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
|
||||||
/* find a specific device, or use -1 for limit if you want unlimited */
|
/* 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,
|
BACNET_OBJECT_TYPE object_type,
|
||||||
uint32_t object_instance, char *object_name)
|
uint32_t object_instance,
|
||||||
|
char *object_name)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int pdu_len = 0;
|
int pdu_len = 0;
|
||||||
|
|||||||
@@ -42,8 +42,10 @@
|
|||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
|
||||||
uint8_t Send_Reinitialize_Device_Request(uint32_t device_id,
|
uint8_t Send_Reinitialize_Device_Request(
|
||||||
BACNET_REINITIALIZED_STATE state, char *password)
|
uint32_t device_id,
|
||||||
|
BACNET_REINITIALIZED_STATE state,
|
||||||
|
char *password)
|
||||||
{
|
{
|
||||||
BACNET_ADDRESS dest;
|
BACNET_ADDRESS dest;
|
||||||
BACNET_ADDRESS my_address;
|
BACNET_ADDRESS my_address;
|
||||||
|
|||||||
@@ -44,10 +44,12 @@
|
|||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
|
||||||
/* returns invoke id of 0 if device is not bound or no tsm available */
|
/* 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,
|
BACNET_OBJECT_TYPE object_type,
|
||||||
uint32_t object_instance,
|
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 dest;
|
||||||
BACNET_ADDRESS my_address;
|
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. */
|
max_apdu in the address binding table. */
|
||||||
if ((unsigned) pdu_len < max_apdu) {
|
if ((unsigned) pdu_len < max_apdu) {
|
||||||
tsm_set_confirmed_unsegmented_transaction(invoke_id, &dest,
|
tsm_set_confirmed_unsegmented_transaction(invoke_id, &dest,
|
||||||
&npdu_data, &Handler_Transmit_Buffer[0],
|
&npdu_data, &Handler_Transmit_Buffer[0], (uint16_t) pdu_len);
|
||||||
(uint16_t) pdu_len);
|
|
||||||
bytes_sent =
|
bytes_sent =
|
||||||
datalink_send_pdu(&dest, &npdu_data,
|
datalink_send_pdu(&dest, &npdu_data,
|
||||||
&Handler_Transmit_Buffer[0], pdu_len);
|
&Handler_Transmit_Buffer[0], pdu_len);
|
||||||
|
|||||||
@@ -42,7 +42,9 @@
|
|||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
#include "txbuf.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 len = 0;
|
||||||
int pdu_len = 0;
|
int pdu_len = 0;
|
||||||
@@ -74,7 +76,9 @@ void Send_TimeSync(BACNET_DATE * bdate, BACNET_TIME * btime)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Send_TimeSyncUTC(BACNET_DATE * bdate, BACNET_TIME * btime)
|
void Send_TimeSyncUTC(
|
||||||
|
BACNET_DATE * bdate,
|
||||||
|
BACNET_TIME * btime)
|
||||||
{
|
{
|
||||||
int pdu_len = 0;
|
int pdu_len = 0;
|
||||||
BACNET_ADDRESS dest;
|
BACNET_ADDRESS dest;
|
||||||
|
|||||||
@@ -43,8 +43,10 @@
|
|||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
|
||||||
/* find a specific device, or use -1 for limit if you want unlimited */
|
/* find a specific device, or use -1 for limit if you want unlimited */
|
||||||
void Send_WhoHas_Name(int32_t low_limit,
|
void Send_WhoHas_Name(
|
||||||
int32_t high_limit, char *object_name)
|
int32_t low_limit,
|
||||||
|
int32_t high_limit,
|
||||||
|
char *object_name)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int pdu_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 */
|
/* 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,
|
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 len = 0;
|
||||||
int pdu_len = 0;
|
int pdu_len = 0;
|
||||||
|
|||||||
@@ -44,7 +44,9 @@
|
|||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
|
||||||
/* find a specific device, or use -1 for limit if you want unlimited */
|
/* 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 len = 0;
|
||||||
int pdu_len = 0;
|
int pdu_len = 0;
|
||||||
|
|||||||
@@ -44,12 +44,15 @@
|
|||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
|
||||||
/* returns the invoke ID for confirmed request, or zero on failure */
|
/* 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,
|
BACNET_OBJECT_TYPE object_type,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID object_property,
|
BACNET_PROPERTY_ID object_property,
|
||||||
uint8_t * application_data,
|
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 dest;
|
||||||
BACNET_ADDRESS my_address;
|
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. */
|
max_apdu in the address binding table. */
|
||||||
if ((unsigned) pdu_len < max_apdu) {
|
if ((unsigned) pdu_len < max_apdu) {
|
||||||
tsm_set_confirmed_unsegmented_transaction(invoke_id, &dest,
|
tsm_set_confirmed_unsegmented_transaction(invoke_id, &dest,
|
||||||
&npdu_data, &Handler_Transmit_Buffer[0],
|
&npdu_data, &Handler_Transmit_Buffer[0], (uint16_t) pdu_len);
|
||||||
(uint16_t) pdu_len);
|
|
||||||
bytes_sent =
|
bytes_sent =
|
||||||
datalink_send_pdu(&dest, &npdu_data,
|
datalink_send_pdu(&dest, &npdu_data,
|
||||||
&Handler_Transmit_Buffer[0], pdu_len);
|
&Handler_Transmit_Buffer[0], pdu_len);
|
||||||
@@ -119,12 +121,14 @@ uint8_t Send_Write_Property_Request_Data(uint32_t device_id,
|
|||||||
return invoke_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,
|
BACNET_OBJECT_TYPE object_type,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID object_property,
|
BACNET_PROPERTY_ID object_property,
|
||||||
BACNET_APPLICATION_DATA_VALUE * object_value,
|
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 };
|
uint8_t application_data[MAX_APDU] = { 0 };
|
||||||
int apdu_len = 0, len = 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
|
#if PRINT_ENABLED_DEBUG
|
||||||
fprintf(stderr, "WriteProperty service: "
|
fprintf(stderr, "WriteProperty service: "
|
||||||
"%s tag=%d\n",
|
"%s tag=%d\n",
|
||||||
(object_value->context_specific?"context":"application"),
|
(object_value->context_specific ? "context" : "application"),
|
||||||
(int)(object_value->context_specific?object_value->context_tag:object_value->tag) );
|
(int) (object_value->context_specific ? object_value->
|
||||||
|
context_tag : object_value->tag));
|
||||||
#endif
|
#endif
|
||||||
len = bacapp_encode_data(&application_data[apdu_len],
|
len = bacapp_encode_data(&application_data[apdu_len], object_value);
|
||||||
object_value);
|
|
||||||
if ((len + apdu_len) < MAX_APDU) {
|
if ((len + apdu_len) < MAX_APDU) {
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -31,13 +31,12 @@
|
|||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "config.h" /* the custom stuff */
|
#include "config.h" /* the custom stuff */
|
||||||
|
|
||||||
#define MAX_ANALOG_INPUTS 7
|
#define MAX_ANALOG_INPUTS 7
|
||||||
|
|
||||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
/* 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_IDENTIFIER,
|
||||||
PROP_OBJECT_NAME,
|
PROP_OBJECT_NAME,
|
||||||
PROP_OBJECT_TYPE,
|
PROP_OBJECT_TYPE,
|
||||||
@@ -49,14 +48,12 @@ static const int Analog_Input_Properties_Required[] =
|
|||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Analog_Input_Properties_Optional[] =
|
static const int Analog_Input_Properties_Optional[] = {
|
||||||
{
|
|
||||||
PROP_DESCRIPTION,
|
PROP_DESCRIPTION,
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Analog_Input_Properties_Proprietary[] =
|
static const int Analog_Input_Properties_Proprietary[] = {
|
||||||
{
|
|
||||||
9997,
|
9997,
|
||||||
9998,
|
9998,
|
||||||
9999,
|
9999,
|
||||||
@@ -81,7 +78,8 @@ void Analog_Input_Property_Lists(
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need validate that the */
|
/* more complex, and then you need validate that the */
|
||||||
/* given instance exists */
|
/* 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)
|
if (object_instance < MAX_ANALOG_INPUTS)
|
||||||
return true;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then count how many you have */
|
/* more complex, and then count how many you have */
|
||||||
unsigned Analog_Input_Count(void)
|
unsigned Analog_Input_Count(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
return MAX_ANALOG_INPUTS;
|
return MAX_ANALOG_INPUTS;
|
||||||
}
|
}
|
||||||
@@ -99,12 +98,14 @@ unsigned Analog_Input_Count(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the instance */
|
/* more complex, and then you need to return the instance */
|
||||||
/* that correlates to the correct index */
|
/* 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;
|
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 */
|
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 */
|
/* return apdu length, or -1 on error */
|
||||||
/* assumption - object has already exists */
|
/* 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,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
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_BIT_STRING bit_string;
|
||||||
BACNET_CHARACTER_STRING char_string;
|
BACNET_CHARACTER_STRING char_string;
|
||||||
float value = 3.14159F;
|
float value = 3.14159F;
|
||||||
|
|
||||||
(void) array_index;
|
(void) array_index;
|
||||||
switch (property) {
|
switch (property) {
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
case PROP_OBJECT_IDENTIFIER:
|
||||||
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
|
apdu_len =
|
||||||
object_instance);
|
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
|
||||||
break;
|
object_instance);
|
||||||
case PROP_OBJECT_NAME:
|
break;
|
||||||
case PROP_DESCRIPTION:
|
case PROP_OBJECT_NAME:
|
||||||
characterstring_init_ansi(&char_string,
|
case PROP_DESCRIPTION:
|
||||||
Analog_Input_Name(object_instance));
|
characterstring_init_ansi(&char_string,
|
||||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
Analog_Input_Name(object_instance));
|
||||||
break;
|
apdu_len =
|
||||||
case PROP_OBJECT_TYPE:
|
encode_application_character_string(&apdu[0], &char_string);
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_ANALOG_INPUT);
|
break;
|
||||||
break;
|
case PROP_OBJECT_TYPE:
|
||||||
case PROP_PRESENT_VALUE:
|
apdu_len =
|
||||||
apdu_len = encode_application_real(&apdu[0], value);
|
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_INPUT);
|
||||||
break;
|
break;
|
||||||
case PROP_STATUS_FLAGS:
|
case PROP_PRESENT_VALUE:
|
||||||
bitstring_init(&bit_string);
|
apdu_len = encode_application_real(&apdu[0], value);
|
||||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
break;
|
||||||
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
case PROP_STATUS_FLAGS:
|
||||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
bitstring_init(&bit_string);
|
||||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||||
break;
|
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||||
case PROP_EVENT_STATE:
|
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||||
break;
|
break;
|
||||||
case PROP_OUT_OF_SERVICE:
|
case PROP_EVENT_STATE:
|
||||||
apdu_len = encode_application_boolean(&apdu[0], false);
|
apdu_len =
|
||||||
break;
|
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||||
case PROP_UNITS:
|
break;
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
|
case PROP_OUT_OF_SERVICE:
|
||||||
break;
|
apdu_len = encode_application_boolean(&apdu[0], false);
|
||||||
case 9997:
|
break;
|
||||||
apdu_len = encode_application_real(&apdu[0], (float) 90.510);
|
case PROP_UNITS:
|
||||||
break;
|
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
|
||||||
case 9998:
|
break;
|
||||||
apdu_len = encode_application_unsigned(&apdu[0], 90);
|
case 9997:
|
||||||
break;
|
apdu_len = encode_application_real(&apdu[0], (float) 90.510);
|
||||||
/* test case for signed encoding-decoding negative value correctly */
|
break;
|
||||||
case 9999:
|
case 9998:
|
||||||
apdu_len = encode_application_signed(&apdu[0], -200);
|
apdu_len = encode_application_unsigned(&apdu[0], 90);
|
||||||
break;
|
break;
|
||||||
default:
|
/* test case for signed encoding-decoding negative value correctly */
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
case 9999:
|
||||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
apdu_len = encode_application_signed(&apdu[0], -200);
|
||||||
apdu_len = -1;
|
break;
|
||||||
break;
|
default:
|
||||||
|
*error_class = ERROR_CLASS_PROPERTY;
|
||||||
|
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
|
apdu_len = -1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
@@ -189,7 +196,8 @@ int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void testAnalogInput(Test * pTest)
|
void testAnalogInput(
|
||||||
|
Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -205,8 +213,7 @@ void testAnalogInput(Test * pTest)
|
|||||||
/* FIXME: we should do a lot more testing here... */
|
/* FIXME: we should do a lot more testing here... */
|
||||||
len = Analog_Input_Encode_Property_APDU(&apdu[0],
|
len = Analog_Input_Encode_Property_APDU(&apdu[0],
|
||||||
instance,
|
instance,
|
||||||
PROP_OBJECT_IDENTIFIER,
|
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
|
||||||
BACNET_ARRAY_ALL, &error_class, &error_code);
|
|
||||||
ct_test(pTest, len >= 0);
|
ct_test(pTest, len >= 0);
|
||||||
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
||||||
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
||||||
@@ -219,7 +226,8 @@ void testAnalogInput(Test * pTest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST_ANALOG_INPUT
|
#ifdef TEST_ANALOG_INPUT
|
||||||
int main(void)
|
int main(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
Test *pTest;
|
Test *pTest;
|
||||||
bool rc;
|
bool rc;
|
||||||
@@ -236,5 +244,5 @@ int main(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* TEST_ANALOG_INPUT */
|
#endif /* TEST_ANALOG_INPUT */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|||||||
+184
-166
@@ -32,7 +32,7 @@
|
|||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
#include "config.h" /* the custom stuff */
|
#include "config.h" /* the custom stuff */
|
||||||
#include "wp.h"
|
#include "wp.h"
|
||||||
|
|
||||||
#define MAX_ANALOG_OUTPUTS 4
|
#define MAX_ANALOG_OUTPUTS 4
|
||||||
@@ -47,8 +47,7 @@
|
|||||||
/* Here is our Priority Array. They are supposed to be Real, but */
|
/* 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 */
|
/* 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. */
|
/* and load a Real for returning the value when asked. */
|
||||||
static uint8_t
|
static uint8_t Analog_Output_Level[MAX_ANALOG_OUTPUTS][BACNET_MAX_PRIORITY];
|
||||||
Analog_Output_Level[MAX_ANALOG_OUTPUTS][BACNET_MAX_PRIORITY];
|
|
||||||
/* Writable out-of-service allows others to play with our Present Value */
|
/* Writable out-of-service allows others to play with our Present Value */
|
||||||
/* without changing the physical output */
|
/* without changing the physical output */
|
||||||
static bool Analog_Output_Out_Of_Service[MAX_ANALOG_OUTPUTS];
|
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;
|
static bool Analog_Output_Initialized = false;
|
||||||
|
|
||||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
/* 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_IDENTIFIER,
|
||||||
PROP_OBJECT_NAME,
|
PROP_OBJECT_NAME,
|
||||||
PROP_OBJECT_TYPE,
|
PROP_OBJECT_TYPE,
|
||||||
@@ -72,14 +70,12 @@ static const int Analog_Output_Properties_Required[] =
|
|||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Analog_Output_Properties_Optional[] =
|
static const int Analog_Output_Properties_Optional[] = {
|
||||||
{
|
|
||||||
PROP_DESCRIPTION,
|
PROP_DESCRIPTION,
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Analog_Output_Properties_Proprietary[] =
|
static const int Analog_Output_Properties_Proprietary[] = {
|
||||||
{
|
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -98,7 +94,8 @@ void Analog_Output_Property_Lists(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Analog_Output_Init(void)
|
void Analog_Output_Init(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
|
|
||||||
@@ -119,7 +116,8 @@ void Analog_Output_Init(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need validate that the */
|
/* more complex, and then you need validate that the */
|
||||||
/* given instance exists */
|
/* given instance exists */
|
||||||
bool Analog_Output_Valid_Instance(uint32_t object_instance)
|
bool Analog_Output_Valid_Instance(
|
||||||
|
uint32_t object_instance)
|
||||||
{
|
{
|
||||||
Analog_Output_Init();
|
Analog_Output_Init();
|
||||||
if (object_instance < MAX_ANALOG_OUTPUTS)
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then count how many you have */
|
/* more complex, and then count how many you have */
|
||||||
unsigned Analog_Output_Count(void)
|
unsigned Analog_Output_Count(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
Analog_Output_Init();
|
Analog_Output_Init();
|
||||||
return MAX_ANALOG_OUTPUTS;
|
return MAX_ANALOG_OUTPUTS;
|
||||||
@@ -139,7 +138,8 @@ unsigned Analog_Output_Count(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the instance */
|
/* more complex, and then you need to return the instance */
|
||||||
/* that correlates to the correct index */
|
/* 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();
|
Analog_Output_Init();
|
||||||
return index;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the index */
|
/* more complex, and then you need to return the index */
|
||||||
/* that correlates to the correct instance number */
|
/* 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;
|
unsigned index = MAX_ANALOG_OUTPUTS;
|
||||||
|
|
||||||
@@ -159,7 +160,8 @@ unsigned Analog_Output_Instance_To_Index(uint32_t object_instance)
|
|||||||
return index;
|
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;
|
float value = AO_RELINQUISH_DEFAULT;
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
@@ -179,10 +181,11 @@ float Analog_Output_Present_Value(uint32_t object_instance)
|
|||||||
return value;
|
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 index = 0; /* instance to index conversion */
|
||||||
unsigned i = 0; /* loop counter */
|
unsigned i = 0; /* loop counter */
|
||||||
unsigned priority = 0; /* return value */
|
unsigned priority = 0; /* return value */
|
||||||
|
|
||||||
Analog_Output_Init();
|
Analog_Output_Init();
|
||||||
@@ -199,8 +202,10 @@ unsigned Analog_Output_Present_Value_Priority(uint32_t object_instance)
|
|||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Analog_Output_Present_Value_Set(uint32_t object_instance,
|
bool Analog_Output_Present_Value_Set(
|
||||||
float value, unsigned priority)
|
uint32_t object_instance,
|
||||||
|
float value,
|
||||||
|
unsigned priority)
|
||||||
{
|
{
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
bool status = false;
|
bool status = false;
|
||||||
@@ -210,7 +215,7 @@ bool Analog_Output_Present_Value_Set(uint32_t object_instance,
|
|||||||
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||||
(priority != 6 /* reserved */ ) &&
|
(priority != 6 /* reserved */ ) &&
|
||||||
(value >= 0.0) && (value <= 100.0)) {
|
(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
|
/* Note: you could set the physical output here to the next
|
||||||
highest priority, or to the relinquish default if no
|
highest priority, or to the relinquish default if no
|
||||||
priorities are set.
|
priorities are set.
|
||||||
@@ -224,7 +229,8 @@ bool Analog_Output_Present_Value_Set(uint32_t object_instance,
|
|||||||
return status;
|
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 priority)
|
||||||
{
|
{
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
@@ -234,7 +240,7 @@ bool Analog_Output_Present_Value_Relinquish(uint32_t object_instance,
|
|||||||
if (index < MAX_ANALOG_OUTPUTS) {
|
if (index < MAX_ANALOG_OUTPUTS) {
|
||||||
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||||
(priority != 6 /* reserved */ )) {
|
(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
|
/* Note: you could set the physical output here to the next
|
||||||
highest priority, or to the relinquish default if no
|
highest priority, or to the relinquish default if no
|
||||||
priorities are set.
|
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 */
|
/* 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 */
|
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 */
|
/* 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,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
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 len = 0;
|
||||||
int apdu_len = 0; /* return value */
|
int apdu_len = 0; /* return value */
|
||||||
BACNET_BIT_STRING bit_string;
|
BACNET_BIT_STRING bit_string;
|
||||||
BACNET_CHARACTER_STRING char_string;
|
BACNET_CHARACTER_STRING char_string;
|
||||||
float real_value = (float) 1.414;
|
float real_value = (float) 1.414;
|
||||||
@@ -279,107 +288,115 @@ int Analog_Output_Encode_Property_APDU(uint8_t * apdu,
|
|||||||
|
|
||||||
Analog_Output_Init();
|
Analog_Output_Init();
|
||||||
switch (property) {
|
switch (property) {
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
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)
|
|
||||||
apdu_len =
|
apdu_len =
|
||||||
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
|
encode_application_object_id(&apdu[0], OBJECT_ANALOG_OUTPUT,
|
||||||
/* if no index was specified, then try to encode the entire list */
|
object_instance);
|
||||||
/* into one packet. */
|
break;
|
||||||
else if (array_index == BACNET_ARRAY_ALL) {
|
case PROP_OBJECT_NAME:
|
||||||
object_index =
|
case PROP_DESCRIPTION:
|
||||||
Analog_Output_Instance_To_Index(object_instance);
|
characterstring_init_ansi(&char_string,
|
||||||
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
|
Analog_Output_Name(object_instance));
|
||||||
/* FIXME: check if we have room before adding it to APDU */
|
apdu_len =
|
||||||
if (Analog_Output_Level[object_index][i] == AO_LEVEL_NULL)
|
encode_application_character_string(&apdu[0], &char_string);
|
||||||
len = encode_application_null(&apdu[apdu_len]);
|
break;
|
||||||
else {
|
case PROP_OBJECT_TYPE:
|
||||||
real_value = Analog_Output_Level[object_index][i];
|
apdu_len =
|
||||||
len = encode_application_real(&apdu[apdu_len], real_value);
|
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_OUTPUT);
|
||||||
}
|
break;
|
||||||
/* add it if we have room */
|
case PROP_PRESENT_VALUE:
|
||||||
if ((apdu_len + len) < MAX_APDU)
|
real_value = Analog_Output_Present_Value(object_instance);
|
||||||
apdu_len += len;
|
apdu_len = encode_application_real(&apdu[0], real_value);
|
||||||
else {
|
break;
|
||||||
*error_class = ERROR_CLASS_SERVICES;
|
case PROP_STATUS_FLAGS:
|
||||||
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
bitstring_init(&bit_string);
|
||||||
apdu_len = -1;
|
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||||
break;
|
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);
|
||||||
} else {
|
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||||
object_index =
|
break;
|
||||||
Analog_Output_Instance_To_Index(object_instance);
|
case PROP_EVENT_STATE:
|
||||||
if (array_index <= BACNET_MAX_PRIORITY) {
|
apdu_len =
|
||||||
if (Analog_Output_Level[object_index][array_index - 1] ==
|
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||||
AO_LEVEL_NULL)
|
break;
|
||||||
apdu_len = encode_application_null(&apdu[0]);
|
case PROP_OUT_OF_SERVICE:
|
||||||
else {
|
object_index = Analog_Output_Instance_To_Index(object_instance);
|
||||||
real_value =
|
state = Analog_Output_Out_Of_Service[object_index];
|
||||||
Analog_Output_Level[object_index][array_index - 1];
|
apdu_len = encode_application_boolean(&apdu[0], state);
|
||||||
apdu_len = encode_application_real(&apdu[0], real_value);
|
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 {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
object_index =
|
||||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
Analog_Output_Instance_To_Index(object_instance);
|
||||||
apdu_len = -1;
|
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;
|
||||||
break;
|
case PROP_RELINQUISH_DEFAULT:
|
||||||
case PROP_RELINQUISH_DEFAULT:
|
real_value = AO_RELINQUISH_DEFAULT;
|
||||||
real_value = AO_RELINQUISH_DEFAULT;
|
apdu_len = encode_application_real(&apdu[0], real_value);
|
||||||
apdu_len = encode_application_real(&apdu[0], real_value);
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
*error_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
apdu_len = -1;
|
||||||
apdu_len = -1;
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns true if successful */
|
/* returns true if successful */
|
||||||
bool Analog_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Analog_Output_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code)
|
||||||
{
|
{
|
||||||
bool status = false; /* return value */
|
bool status = false; /* return value */
|
||||||
unsigned int object_index = 0;
|
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 < application_data_len: more data? */
|
||||||
/* FIXME: len == 0: unable to decode? */
|
/* FIXME: len == 0: unable to decode? */
|
||||||
switch (wp_data->object_property) {
|
switch (wp_data->object_property) {
|
||||||
case PROP_PRESENT_VALUE:
|
case PROP_PRESENT_VALUE:
|
||||||
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
|
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
|
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||||
algorithm and may not be used for other purposes in any
|
algorithm and may not be used for other purposes in any
|
||||||
object. */
|
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_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||||
} else if (!status) {
|
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
|
||||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
|
||||||
}
|
}
|
||||||
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
|
break;
|
||||||
level = AO_LEVEL_NULL;
|
case PROP_OUT_OF_SERVICE:
|
||||||
object_index =
|
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
|
||||||
Analog_Output_Instance_To_Index(wp_data->object_instance);
|
object_index =
|
||||||
status =
|
Analog_Output_Instance_To_Index(wp_data->object_instance);
|
||||||
Analog_Output_Present_Value_Relinquish(wp_data->
|
Analog_Output_Out_Of_Service[object_index] =
|
||||||
object_instance, wp_data->priority);
|
value.type.Boolean;
|
||||||
if (!status) {
|
status = true;
|
||||||
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*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_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||||
}
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -460,7 +477,8 @@ bool Analog_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void testAnalogOutput(Test * pTest)
|
void testAnalogOutput(
|
||||||
|
Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -475,8 +493,7 @@ void testAnalogOutput(Test * pTest)
|
|||||||
|
|
||||||
len = Analog_Output_Encode_Property_APDU(&apdu[0],
|
len = Analog_Output_Encode_Property_APDU(&apdu[0],
|
||||||
instance,
|
instance,
|
||||||
PROP_OBJECT_IDENTIFIER,
|
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
|
||||||
BACNET_ARRAY_ALL, &error_class, &error_code);
|
|
||||||
ct_test(pTest, len != 0);
|
ct_test(pTest, len != 0);
|
||||||
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
||||||
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
||||||
@@ -489,7 +506,8 @@ void testAnalogOutput(Test * pTest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST_ANALOG_OUTPUT
|
#ifdef TEST_ANALOG_OUTPUT
|
||||||
int main(void)
|
int main(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
Test *pTest;
|
Test *pTest;
|
||||||
bool rc;
|
bool rc;
|
||||||
@@ -506,5 +524,5 @@ int main(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* TEST_ANALOG_INPUT */
|
#endif /* TEST_ANALOG_INPUT */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|||||||
+186
-170
@@ -32,7 +32,7 @@
|
|||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
#include "config.h" /* the custom stuff */
|
#include "config.h" /* the custom stuff */
|
||||||
#include "wp.h"
|
#include "wp.h"
|
||||||
|
|
||||||
#define MAX_ANALOG_VALUES 4
|
#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;
|
static bool Analog_Value_Initialized = false;
|
||||||
|
|
||||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
/* 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_IDENTIFIER,
|
||||||
PROP_OBJECT_NAME,
|
PROP_OBJECT_NAME,
|
||||||
PROP_OBJECT_TYPE,
|
PROP_OBJECT_TYPE,
|
||||||
@@ -69,16 +68,14 @@ static const int Analog_Value_Properties_Required[] =
|
|||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Analog_Value_Properties_Optional[] =
|
static const int Analog_Value_Properties_Optional[] = {
|
||||||
{
|
|
||||||
PROP_DESCRIPTION,
|
PROP_DESCRIPTION,
|
||||||
PROP_PRIORITY_ARRAY,
|
PROP_PRIORITY_ARRAY,
|
||||||
PROP_RELINQUISH_DEFAULT,
|
PROP_RELINQUISH_DEFAULT,
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Analog_Value_Properties_Proprietary[] =
|
static const int Analog_Value_Properties_Proprietary[] = {
|
||||||
{
|
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -97,7 +94,8 @@ void Analog_Value_Property_Lists(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Analog_Value_Init(void)
|
void Analog_Value_Init(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
|
|
||||||
@@ -118,7 +116,8 @@ void Analog_Value_Init(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need validate that the */
|
/* more complex, and then you need validate that the */
|
||||||
/* given instance exists */
|
/* given instance exists */
|
||||||
bool Analog_Value_Valid_Instance(uint32_t object_instance)
|
bool Analog_Value_Valid_Instance(
|
||||||
|
uint32_t object_instance)
|
||||||
{
|
{
|
||||||
Analog_Value_Init();
|
Analog_Value_Init();
|
||||||
if (object_instance < MAX_ANALOG_VALUES)
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then count how many you have */
|
/* more complex, and then count how many you have */
|
||||||
unsigned Analog_Value_Count(void)
|
unsigned Analog_Value_Count(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
Analog_Value_Init();
|
Analog_Value_Init();
|
||||||
return MAX_ANALOG_VALUES;
|
return MAX_ANALOG_VALUES;
|
||||||
@@ -138,7 +138,8 @@ unsigned Analog_Value_Count(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the instance */
|
/* more complex, and then you need to return the instance */
|
||||||
/* that correlates to the correct index */
|
/* 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();
|
Analog_Value_Init();
|
||||||
return index;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the index */
|
/* more complex, and then you need to return the index */
|
||||||
/* that correlates to the correct instance number */
|
/* 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;
|
unsigned index = MAX_ANALOG_VALUES;
|
||||||
|
|
||||||
@@ -158,7 +160,8 @@ unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
|
|||||||
return index;
|
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;
|
float value = ANALOG_RELINQUISH_DEFAULT;
|
||||||
unsigned index = 0;
|
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 */
|
/* 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 */
|
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 */
|
/* 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,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
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 len = 0;
|
||||||
int apdu_len = 0; /* return value */
|
int apdu_len = 0; /* return value */
|
||||||
BACNET_BIT_STRING bit_string;
|
BACNET_BIT_STRING bit_string;
|
||||||
BACNET_CHARACTER_STRING char_string;
|
BACNET_CHARACTER_STRING char_string;
|
||||||
float real_value = (float) 1.414;
|
float real_value = (float) 1.414;
|
||||||
@@ -209,106 +215,115 @@ int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
|
|||||||
|
|
||||||
Analog_Value_Init();
|
Analog_Value_Init();
|
||||||
switch (property) {
|
switch (property) {
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
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)
|
|
||||||
apdu_len =
|
apdu_len =
|
||||||
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
|
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
|
||||||
/* if no index was specified, then try to encode the entire list */
|
object_instance);
|
||||||
/* into one packet. */
|
break;
|
||||||
else if (array_index == BACNET_ARRAY_ALL) {
|
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);
|
object_index = Analog_Value_Instance_To_Index(object_instance);
|
||||||
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
|
state = Analog_Value_Out_Of_Service[object_index];
|
||||||
/* FIXME: check if we have room before adding it to APDU */
|
apdu_len = encode_application_boolean(&apdu[0], state);
|
||||||
if (Analog_Value_Level[object_index][i] ==
|
break;
|
||||||
ANALOG_LEVEL_NULL)
|
case PROP_UNITS:
|
||||||
len = encode_application_null(&apdu[apdu_len]);
|
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
|
||||||
else {
|
break;
|
||||||
real_value = Analog_Value_Level[object_index][i];
|
case PROP_PRIORITY_ARRAY:
|
||||||
len = encode_application_real(&apdu[apdu_len], real_value);
|
/* Array element zero is the number of elements in the array */
|
||||||
}
|
if (array_index == 0)
|
||||||
/* add it if we have room */
|
apdu_len =
|
||||||
if ((apdu_len + len) < MAX_APDU)
|
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
|
||||||
apdu_len += len;
|
/* if no index was specified, then try to encode the entire list */
|
||||||
else {
|
/* into one packet. */
|
||||||
*error_class = ERROR_CLASS_SERVICES;
|
else if (array_index == BACNET_ARRAY_ALL) {
|
||||||
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
object_index = Analog_Value_Instance_To_Index(object_instance);
|
||||||
apdu_len = -1;
|
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
|
||||||
break;
|
/* FIXME: check if we have room before adding it to APDU */
|
||||||
}
|
if (Analog_Value_Level[object_index][i] ==
|
||||||
}
|
ANALOG_LEVEL_NULL)
|
||||||
} else {
|
len = encode_application_null(&apdu[apdu_len]);
|
||||||
object_index = Analog_Value_Instance_To_Index(object_instance);
|
else {
|
||||||
if (array_index <= BACNET_MAX_PRIORITY) {
|
real_value = Analog_Value_Level[object_index][i];
|
||||||
if (Analog_Value_Level[object_index][array_index - 1] ==
|
len =
|
||||||
ANALOG_LEVEL_NULL)
|
encode_application_real(&apdu[apdu_len],
|
||||||
apdu_len = encode_application_null(&apdu[0]);
|
real_value);
|
||||||
else {
|
}
|
||||||
real_value =
|
/* add it if we have room */
|
||||||
Analog_Value_Level[object_index][array_index - 1];
|
if ((apdu_len + len) < MAX_APDU)
|
||||||
apdu_len = encode_application_real(&apdu[0], real_value);
|
apdu_len += len;
|
||||||
|
else {
|
||||||
|
*error_class = ERROR_CLASS_SERVICES;
|
||||||
|
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
||||||
|
apdu_len = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
object_index = Analog_Value_Instance_To_Index(object_instance);
|
||||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
if (array_index <= BACNET_MAX_PRIORITY) {
|
||||||
apdu_len = -1;
|
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;
|
break;
|
||||||
case PROP_RELINQUISH_DEFAULT:
|
case PROP_RELINQUISH_DEFAULT:
|
||||||
real_value = ANALOG_RELINQUISH_DEFAULT;
|
real_value = ANALOG_RELINQUISH_DEFAULT;
|
||||||
apdu_len = encode_application_real(&apdu[0], real_value);
|
apdu_len = encode_application_real(&apdu[0], real_value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*error_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
apdu_len = -1;
|
apdu_len = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns true if successful */
|
/* returns true if successful */
|
||||||
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Analog_Value_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code)
|
||||||
{
|
{
|
||||||
bool status = false; /* return value */
|
bool status = false; /* return value */
|
||||||
unsigned int object_index = 0;
|
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 < application_data_len: more data? */
|
||||||
/* FIXME: len == 0: unable to decode? */
|
/* FIXME: len == 0: unable to decode? */
|
||||||
switch (wp_data->object_property) {
|
switch (wp_data->object_property) {
|
||||||
case PROP_PRESENT_VALUE:
|
case PROP_PRESENT_VALUE:
|
||||||
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
|
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
|
||||||
priority = wp_data->priority;
|
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) {
|
|
||||||
/* Command priority 6 is reserved for use by Minimum On/Off
|
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||||
algorithm and may not be used for other purposes in any
|
algorithm and may not be used for other purposes in any
|
||||||
object. */
|
object. */
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
(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 {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*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) {
|
break;
|
||||||
level = ANALOG_LEVEL_NULL;
|
case PROP_OUT_OF_SERVICE:
|
||||||
object_index =
|
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
|
||||||
Analog_Value_Instance_To_Index(wp_data->object_instance);
|
object_index =
|
||||||
priority = wp_data->priority;
|
Analog_Value_Instance_To_Index(wp_data->object_instance);
|
||||||
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
|
Analog_Value_Out_Of_Service[object_index] = value.type.Boolean;
|
||||||
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;
|
status = true;
|
||||||
} else {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*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_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||||
}
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -410,7 +425,8 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void testAnalog_Value(Test * pTest)
|
void testAnalog_Value(
|
||||||
|
Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -425,8 +441,7 @@ void testAnalog_Value(Test * pTest)
|
|||||||
|
|
||||||
len = Analog_Value_Encode_Property_APDU(&apdu[0],
|
len = Analog_Value_Encode_Property_APDU(&apdu[0],
|
||||||
instance,
|
instance,
|
||||||
PROP_OBJECT_IDENTIFIER,
|
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
|
||||||
BACNET_ARRAY_ALL, &error_class, &error_code);
|
|
||||||
ct_test(pTest, len != 0);
|
ct_test(pTest, len != 0);
|
||||||
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
||||||
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
||||||
@@ -439,7 +454,8 @@ void testAnalog_Value(Test * pTest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST_ANALOG_VALUE
|
#ifdef TEST_ANALOG_VALUE
|
||||||
int main(void)
|
int main(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
Test *pTest;
|
Test *pTest;
|
||||||
bool rc;
|
bool rc;
|
||||||
@@ -456,5 +472,5 @@ int main(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* TEST_ANALOG_VALUE */
|
#endif /* TEST_ANALOG_VALUE */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|||||||
+137
-123
@@ -49,12 +49,11 @@ static BACNET_FILE_LISTING BACnet_File_Listing[] = {
|
|||||||
{0, "temp_0.txt"},
|
{0, "temp_0.txt"},
|
||||||
{1, "temp_1.txt"},
|
{1, "temp_1.txt"},
|
||||||
{2, "temp_2.txt"},
|
{2, "temp_2.txt"},
|
||||||
{0, NULL} /* last file indication */
|
{0, NULL} /* last file indication */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
/* 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_IDENTIFIER,
|
||||||
PROP_OBJECT_NAME,
|
PROP_OBJECT_NAME,
|
||||||
PROP_OBJECT_TYPE,
|
PROP_OBJECT_TYPE,
|
||||||
@@ -67,14 +66,12 @@ static const int bacfile_Properties_Required[] =
|
|||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int bacfile_Properties_Optional[] =
|
static const int bacfile_Properties_Optional[] = {
|
||||||
{
|
|
||||||
PROP_DESCRIPTION,
|
PROP_DESCRIPTION,
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int bacfile_Properties_Proprietary[] =
|
static const int bacfile_Properties_Proprietary[] = {
|
||||||
{
|
|
||||||
-1
|
-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;
|
uint32_t index = 0;
|
||||||
char *filename = NULL;
|
char *filename = NULL;
|
||||||
@@ -111,12 +109,14 @@ char *bacfile_name(uint32_t instance)
|
|||||||
return filename;
|
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;
|
return bacfile_name(object_instance) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t bacfile_count(void)
|
uint32_t bacfile_count(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
|
|
||||||
@@ -128,7 +128,8 @@ uint32_t bacfile_count(void)
|
|||||||
return index;
|
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 instance = BACNET_MAX_INSTANCE + 1;
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
@@ -145,7 +146,8 @@ uint32_t bacfile_index_to_instance(unsigned find_index)
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long fsize(FILE * pFile)
|
static long fsize(
|
||||||
|
FILE * pFile)
|
||||||
{
|
{
|
||||||
long size = 0;
|
long size = 0;
|
||||||
long origin = 0;
|
long origin = 0;
|
||||||
@@ -159,7 +161,8 @@ static long fsize(FILE * pFile)
|
|||||||
return (size);
|
return (size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned bacfile_file_size(uint32_t object_instance)
|
static unsigned bacfile_file_size(
|
||||||
|
uint32_t object_instance)
|
||||||
{
|
{
|
||||||
char *pFilename = NULL;
|
char *pFilename = NULL;
|
||||||
FILE *pFile = 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 */
|
/* 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,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
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] = { "" };
|
char text_string[32] = { "" };
|
||||||
BACNET_CHARACTER_STRING char_string;
|
BACNET_CHARACTER_STRING char_string;
|
||||||
BACNET_DATE bdate;
|
BACNET_DATE bdate;
|
||||||
@@ -192,76 +197,82 @@ int bacfile_encode_property_apdu(uint8_t * apdu,
|
|||||||
|
|
||||||
(void) array_index;
|
(void) array_index;
|
||||||
switch (property) {
|
switch (property) {
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
case PROP_OBJECT_IDENTIFIER:
|
||||||
apdu_len = encode_application_object_id(&apdu[0],
|
apdu_len = encode_application_object_id(&apdu[0],
|
||||||
OBJECT_FILE, object_instance);
|
OBJECT_FILE, object_instance);
|
||||||
break;
|
break;
|
||||||
case PROP_OBJECT_NAME:
|
case PROP_OBJECT_NAME:
|
||||||
sprintf(text_string, "FILE %d", object_instance);
|
sprintf(text_string, "FILE %d", object_instance);
|
||||||
characterstring_init_ansi(&char_string, text_string);
|
characterstring_init_ansi(&char_string, text_string);
|
||||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
apdu_len =
|
||||||
break;
|
encode_application_character_string(&apdu[0], &char_string);
|
||||||
case PROP_OBJECT_TYPE:
|
break;
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_FILE);
|
case PROP_OBJECT_TYPE:
|
||||||
break;
|
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_FILE);
|
||||||
case PROP_DESCRIPTION:
|
break;
|
||||||
characterstring_init_ansi(&char_string,
|
case PROP_DESCRIPTION:
|
||||||
bacfile_name(object_instance));
|
characterstring_init_ansi(&char_string,
|
||||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
bacfile_name(object_instance));
|
||||||
break;
|
apdu_len =
|
||||||
case PROP_FILE_TYPE:
|
encode_application_character_string(&apdu[0], &char_string);
|
||||||
characterstring_init_ansi(&char_string, "TEXT");
|
break;
|
||||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
case PROP_FILE_TYPE:
|
||||||
break;
|
characterstring_init_ansi(&char_string, "TEXT");
|
||||||
case PROP_FILE_SIZE:
|
apdu_len =
|
||||||
apdu_len = encode_application_unsigned(&apdu[0],
|
encode_application_character_string(&apdu[0], &char_string);
|
||||||
bacfile_file_size(object_instance));
|
break;
|
||||||
break;
|
case PROP_FILE_SIZE:
|
||||||
case PROP_MODIFICATION_DATE:
|
apdu_len = encode_application_unsigned(&apdu[0],
|
||||||
/* FIXME: get the actual value instead of April Fool's Day */
|
bacfile_file_size(object_instance));
|
||||||
bdate.year = 2006; /* AD */
|
break;
|
||||||
bdate.month = 4; /* 1=Jan */
|
case PROP_MODIFICATION_DATE:
|
||||||
bdate.day = 1; /* 1..31 */
|
/* FIXME: get the actual value instead of April Fool's Day */
|
||||||
bdate.wday = 6; /* 1=Monday */
|
bdate.year = 2006; /* AD */
|
||||||
apdu_len = encode_application_date(&apdu[0], &bdate);
|
bdate.month = 4; /* 1=Jan */
|
||||||
/* FIXME: get the actual value */
|
bdate.day = 1; /* 1..31 */
|
||||||
btime.hour = 7;
|
bdate.wday = 6; /* 1=Monday */
|
||||||
btime.min = 0;
|
apdu_len = encode_application_date(&apdu[0], &bdate);
|
||||||
btime.sec = 3;
|
/* FIXME: get the actual value */
|
||||||
btime.hundredths = 1;
|
btime.hour = 7;
|
||||||
apdu_len += encode_application_time(&apdu[apdu_len], &btime);
|
btime.min = 0;
|
||||||
break;
|
btime.sec = 3;
|
||||||
case PROP_ARCHIVE:
|
btime.hundredths = 1;
|
||||||
/* 12.13.8 Archive
|
apdu_len += encode_application_time(&apdu[apdu_len], &btime);
|
||||||
This property, of type BOOLEAN, indicates whether the File
|
break;
|
||||||
object has been saved for historical or backup purposes. This
|
case PROP_ARCHIVE:
|
||||||
property shall be logical TRUE only if no changes have been
|
/* 12.13.8 Archive
|
||||||
made to the file data by internal processes or through File
|
This property, of type BOOLEAN, indicates whether the File
|
||||||
Access Services since the last time the object was archived.
|
object has been saved for historical or backup purposes. This
|
||||||
*/
|
property shall be logical TRUE only if no changes have been
|
||||||
/* FIXME: get the actual value: note it may be inverse... */
|
made to the file data by internal processes or through File
|
||||||
apdu_len = encode_application_boolean(&apdu[0], true);
|
Access Services since the last time the object was archived.
|
||||||
break;
|
*/
|
||||||
case PROP_READ_ONLY:
|
/* FIXME: get the actual value: note it may be inverse... */
|
||||||
/* FIXME: get the actual value */
|
apdu_len = encode_application_boolean(&apdu[0], true);
|
||||||
apdu_len = encode_application_boolean(&apdu[0], true);
|
break;
|
||||||
break;
|
case PROP_READ_ONLY:
|
||||||
case PROP_FILE_ACCESS_METHOD:
|
/* FIXME: get the actual value */
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], FILE_STREAM_ACCESS);
|
apdu_len = encode_application_boolean(&apdu[0], true);
|
||||||
break;
|
break;
|
||||||
default:
|
case PROP_FILE_ACCESS_METHOD:
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
apdu_len =
|
||||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
encode_application_enumerated(&apdu[0], FILE_STREAM_ACCESS);
|
||||||
apdu_len = -1;
|
break;
|
||||||
break;
|
default:
|
||||||
|
*error_class = ERROR_CLASS_PROPERTY;
|
||||||
|
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
|
apdu_len = -1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns true if successful */
|
/* returns true if successful */
|
||||||
bool bacfile_write_property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool bacfile_write_property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code)
|
||||||
{
|
{
|
||||||
bool status = false; /* return value */
|
bool status = false; /* return value */
|
||||||
int len = 0;
|
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 < application_data_len: more data? */
|
||||||
/* FIXME: len == 0: unable to decode? */
|
/* FIXME: len == 0: unable to decode? */
|
||||||
switch (wp_data->object_property) {
|
switch (wp_data->object_property) {
|
||||||
case PROP_ARCHIVE:
|
case PROP_ARCHIVE:
|
||||||
/* 12.13.8 Archive
|
/* 12.13.8 Archive
|
||||||
This property, of type BOOLEAN, indicates whether the File
|
This property, of type BOOLEAN, indicates whether the File
|
||||||
object has been saved for historical or backup purposes. This
|
object has been saved for historical or backup purposes. This
|
||||||
property shall be logical TRUE only if no changes have been
|
property shall be logical TRUE only if no changes have been
|
||||||
made to the file data by internal processes or through File
|
made to the file data by internal processes or through File
|
||||||
Access Services since the last time the object was archived. */
|
Access Services since the last time the object was archived. */
|
||||||
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
|
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
|
||||||
if (value.type.Boolean) {
|
if (value.type.Boolean) {
|
||||||
/* FIXME: do something to wp_data->object_instance */
|
/* FIXME: do something to wp_data->object_instance */
|
||||||
|
} else {
|
||||||
|
/* FIXME: do something to wp_data->object_instance */
|
||||||
|
}
|
||||||
} else {
|
} 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_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||||
}
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
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 index = 0;
|
||||||
uint32_t instance = BACNET_MAX_INSTANCE + 1;
|
uint32_t instance = BACNET_MAX_INSTANCE + 1;
|
||||||
@@ -343,7 +355,8 @@ uint32_t bacfile_instance(char *filename)
|
|||||||
/* Another way would be to store the */
|
/* Another way would be to store the */
|
||||||
/* invokeID and file instance in a list or table */
|
/* invokeID and file instance in a list or table */
|
||||||
/* when the request was sent */
|
/* 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_NPDU_DATA npdu_data = { 0 }; /* dummy for getting npdu length */
|
||||||
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
|
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 */
|
BACNET_ADDRESS dest; /* where the original packet was destined */
|
||||||
uint8_t apdu[MAX_PDU] = { 0 }; /* original APDU packet */
|
uint8_t apdu[MAX_PDU] = { 0 }; /* original APDU packet */
|
||||||
uint16_t apdu_len = 0; /* original APDU packet length */
|
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 };
|
BACNET_ATOMIC_READ_FILE_DATA data = { 0 };
|
||||||
uint32_t object_instance = BACNET_MAX_INSTANCE + 1; /* return value */
|
uint32_t object_instance = BACNET_MAX_INSTANCE + 1; /* return value */
|
||||||
bool found = false;
|
bool found = false;
|
||||||
@@ -383,7 +396,8 @@ uint32_t bacfile_instance_from_tsm(uint8_t invokeID)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA * data)
|
bool bacfile_read_data(
|
||||||
|
BACNET_ATOMIC_READ_FILE_DATA * data)
|
||||||
{
|
{
|
||||||
char *pFilename = NULL;
|
char *pFilename = NULL;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
@@ -395,8 +409,7 @@ bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA * data)
|
|||||||
found = true;
|
found = true;
|
||||||
pFile = fopen(pFilename, "rb");
|
pFile = fopen(pFilename, "rb");
|
||||||
if (pFile) {
|
if (pFile) {
|
||||||
(void) fseek(pFile,
|
(void) fseek(pFile, data->type.stream.fileStartPosition, SEEK_SET);
|
||||||
data->type.stream.fileStartPosition, SEEK_SET);
|
|
||||||
len = fread(octetstring_value(&data->fileData), 1,
|
len = fread(octetstring_value(&data->fileData), 1,
|
||||||
data->type.stream.requestedOctetCount, pFile);
|
data->type.stream.requestedOctetCount, pFile);
|
||||||
if (len < data->type.stream.requestedOctetCount)
|
if (len < data->type.stream.requestedOctetCount)
|
||||||
@@ -417,7 +430,8 @@ bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA * data)
|
|||||||
return found;
|
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;
|
char *pFilename = NULL;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
@@ -428,15 +442,15 @@ bool bacfile_write_stream_data(BACNET_ATOMIC_WRITE_FILE_DATA * data)
|
|||||||
found = true;
|
found = true;
|
||||||
/* open the file as a clean slate when starting at 0 */
|
/* open the file as a clean slate when starting at 0 */
|
||||||
if (data->type.stream.fileStartPosition == 0)
|
if (data->type.stream.fileStartPosition == 0)
|
||||||
pFile = fopen(pFilename, "wb");
|
pFile = fopen(pFilename, "wb");
|
||||||
else
|
else
|
||||||
pFile = fopen(pFilename, "rb+");
|
pFile = fopen(pFilename, "rb+");
|
||||||
if (pFile) {
|
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),
|
if (fwrite(octetstring_value(&data->fileData),
|
||||||
octetstring_length(&data->fileData),1,pFile) != 1) {
|
octetstring_length(&data->fileData), 1, pFile) != 1) {
|
||||||
|
|
||||||
}
|
}
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,15 +31,14 @@
|
|||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "config.h" /* the custom stuff */
|
#include "config.h" /* the custom stuff */
|
||||||
|
|
||||||
#define MAX_BINARY_INPUTS 5
|
#define MAX_BINARY_INPUTS 5
|
||||||
|
|
||||||
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
|
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
|
||||||
|
|
||||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
/* 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_IDENTIFIER,
|
||||||
PROP_OBJECT_NAME,
|
PROP_OBJECT_NAME,
|
||||||
PROP_OBJECT_TYPE,
|
PROP_OBJECT_TYPE,
|
||||||
@@ -51,14 +50,12 @@ static const int Binary_Input_Properties_Required[] =
|
|||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Binary_Input_Properties_Optional[] =
|
static const int Binary_Input_Properties_Optional[] = {
|
||||||
{
|
|
||||||
PROP_DESCRIPTION,
|
PROP_DESCRIPTION,
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Binary_Input_Properties_Proprietary[] =
|
static const int Binary_Input_Properties_Proprietary[] = {
|
||||||
{
|
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,7 +77,8 @@ void Binary_Input_Property_Lists(
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need validate that the */
|
/* more complex, and then you need validate that the */
|
||||||
/* given instance exists */
|
/* 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)
|
if (object_instance < MAX_BINARY_INPUTS)
|
||||||
return true;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then count how many you have */
|
/* more complex, and then count how many you have */
|
||||||
unsigned Binary_Input_Count(void)
|
unsigned Binary_Input_Count(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
return MAX_BINARY_INPUTS;
|
return MAX_BINARY_INPUTS;
|
||||||
}
|
}
|
||||||
@@ -98,12 +97,14 @@ unsigned Binary_Input_Count(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the instance */
|
/* more complex, and then you need to return the instance */
|
||||||
/* that correlates to the correct index */
|
/* 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;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Binary_Input_Init(void)
|
void Binary_Input_Init(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@@ -123,7 +124,8 @@ void Binary_Input_Init(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the index */
|
/* more complex, and then you need to return the index */
|
||||||
/* that correlates to the correct instance number */
|
/* 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;
|
unsigned index = MAX_BINARY_INPUTS;
|
||||||
|
|
||||||
@@ -134,8 +136,8 @@ unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t
|
static BACNET_BINARY_PV Binary_Input_Present_Value(
|
||||||
object_instance)
|
uint32_t object_instance)
|
||||||
{
|
{
|
||||||
BACNET_BINARY_PV value = BINARY_INACTIVE;
|
BACNET_BINARY_PV value = BINARY_INACTIVE;
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
@@ -148,7 +150,8 @@ static BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t
|
|||||||
return value;
|
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 */
|
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 */
|
/* return apdu length, or -1 on error */
|
||||||
/* assumption - object already exists, and has been bounds checked */
|
/* 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,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
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_BIT_STRING bit_string;
|
||||||
BACNET_CHARACTER_STRING char_string;
|
BACNET_CHARACTER_STRING char_string;
|
||||||
BACNET_POLARITY polarity = POLARITY_NORMAL;
|
BACNET_POLARITY polarity = POLARITY_NORMAL;
|
||||||
@@ -178,50 +183,54 @@ int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
|
|||||||
(void) array_index;
|
(void) array_index;
|
||||||
Binary_Input_Init();
|
Binary_Input_Init();
|
||||||
switch (property) {
|
switch (property) {
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
case PROP_OBJECT_IDENTIFIER:
|
||||||
apdu_len = encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
|
apdu_len =
|
||||||
object_instance);
|
encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
|
||||||
break;
|
object_instance);
|
||||||
case PROP_OBJECT_NAME:
|
break;
|
||||||
case PROP_DESCRIPTION:
|
case PROP_OBJECT_NAME:
|
||||||
/* note: object name must be unique in our device */
|
case PROP_DESCRIPTION:
|
||||||
characterstring_init_ansi(&char_string,
|
/* note: object name must be unique in our device */
|
||||||
Binary_Input_Name(object_instance));
|
characterstring_init_ansi(&char_string,
|
||||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
Binary_Input_Name(object_instance));
|
||||||
break;
|
apdu_len =
|
||||||
case PROP_OBJECT_TYPE:
|
encode_application_character_string(&apdu[0], &char_string);
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_BINARY_INPUT);
|
break;
|
||||||
break;
|
case PROP_OBJECT_TYPE:
|
||||||
case PROP_PRESENT_VALUE:
|
apdu_len =
|
||||||
/* note: you need to look up the actual value */
|
encode_application_enumerated(&apdu[0], OBJECT_BINARY_INPUT);
|
||||||
apdu_len =
|
break;
|
||||||
encode_application_enumerated(&apdu[0],
|
case PROP_PRESENT_VALUE:
|
||||||
Binary_Input_Present_Value(object_instance));
|
/* note: you need to look up the actual value */
|
||||||
break;
|
apdu_len =
|
||||||
case PROP_STATUS_FLAGS:
|
encode_application_enumerated(&apdu[0],
|
||||||
/* note: see the details in the standard on how to use these */
|
Binary_Input_Present_Value(object_instance));
|
||||||
bitstring_init(&bit_string);
|
break;
|
||||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
case PROP_STATUS_FLAGS:
|
||||||
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
/* note: see the details in the standard on how to use these */
|
||||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
bitstring_init(&bit_string);
|
||||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||||
break;
|
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||||
case PROP_EVENT_STATE:
|
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||||
/* note: see the details in the standard on how to use this */
|
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
break;
|
||||||
break;
|
case PROP_EVENT_STATE:
|
||||||
case PROP_OUT_OF_SERVICE:
|
/* note: see the details in the standard on how to use this */
|
||||||
apdu_len = encode_application_boolean(&apdu[0], false);
|
apdu_len =
|
||||||
break;
|
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||||
case PROP_POLARITY:
|
break;
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], polarity);
|
case PROP_OUT_OF_SERVICE:
|
||||||
break;
|
apdu_len = encode_application_boolean(&apdu[0], false);
|
||||||
default:
|
break;
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
case PROP_POLARITY:
|
||||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
apdu_len = encode_application_enumerated(&apdu[0], polarity);
|
||||||
apdu_len = -1;
|
break;
|
||||||
break;
|
default:
|
||||||
|
*error_class = ERROR_CLASS_PROPERTY;
|
||||||
|
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
|
apdu_len = -1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
@@ -232,7 +241,8 @@ int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void testBinaryInput(Test * pTest)
|
void testBinaryInput(
|
||||||
|
Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -248,8 +258,7 @@ void testBinaryInput(Test * pTest)
|
|||||||
/* FIXME: we should do a lot more testing here... */
|
/* FIXME: we should do a lot more testing here... */
|
||||||
len = Binary_Input_Encode_Property_APDU(&apdu[0],
|
len = Binary_Input_Encode_Property_APDU(&apdu[0],
|
||||||
instance,
|
instance,
|
||||||
PROP_OBJECT_IDENTIFIER,
|
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
|
||||||
BACNET_ARRAY_ALL, &error_class, &error_code);
|
|
||||||
ct_test(pTest, len >= 0);
|
ct_test(pTest, len >= 0);
|
||||||
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
||||||
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
||||||
@@ -262,7 +271,8 @@ void testBinaryInput(Test * pTest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST_BINARY_INPUT
|
#ifdef TEST_BINARY_INPUT
|
||||||
int main(void)
|
int main(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
Test *pTest;
|
Test *pTest;
|
||||||
bool rc;
|
bool rc;
|
||||||
@@ -279,5 +289,5 @@ int main(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* TEST_BINARY_INPUT */
|
#endif /* TEST_BINARY_INPUT */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|||||||
+195
-184
@@ -32,7 +32,7 @@
|
|||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
#include "config.h" /* the custom stuff */
|
#include "config.h" /* the custom stuff */
|
||||||
#include "wp.h"
|
#include "wp.h"
|
||||||
|
|
||||||
#define MAX_BINARY_OUTPUTS 6
|
#define MAX_BINARY_OUTPUTS 6
|
||||||
@@ -48,8 +48,7 @@ static BACNET_BINARY_PV
|
|||||||
static bool Binary_Output_Out_Of_Service[MAX_BINARY_OUTPUTS];
|
static bool Binary_Output_Out_Of_Service[MAX_BINARY_OUTPUTS];
|
||||||
|
|
||||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
/* 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_IDENTIFIER,
|
||||||
PROP_OBJECT_NAME,
|
PROP_OBJECT_NAME,
|
||||||
PROP_OBJECT_TYPE,
|
PROP_OBJECT_TYPE,
|
||||||
@@ -63,14 +62,12 @@ static const int Binary_Output_Properties_Required[] =
|
|||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Binary_Output_Properties_Optional[] =
|
static const int Binary_Output_Properties_Optional[] = {
|
||||||
{
|
|
||||||
PROP_DESCRIPTION,
|
PROP_DESCRIPTION,
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Binary_Output_Properties_Proprietary[] =
|
static const int Binary_Output_Properties_Proprietary[] = {
|
||||||
{
|
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,7 +86,8 @@ void Binary_Output_Property_Lists(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Binary_Output_Init(void)
|
void Binary_Output_Init(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
@@ -111,7 +109,8 @@ void Binary_Output_Init(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need validate that the */
|
/* more complex, and then you need validate that the */
|
||||||
/* given instance exists */
|
/* 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)
|
if (object_instance < MAX_BINARY_OUTPUTS)
|
||||||
return true;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then count how many you have */
|
/* more complex, and then count how many you have */
|
||||||
unsigned Binary_Output_Count(void)
|
unsigned Binary_Output_Count(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
return MAX_BINARY_OUTPUTS;
|
return MAX_BINARY_OUTPUTS;
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,8 @@ unsigned Binary_Output_Count(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the instance */
|
/* more complex, and then you need to return the instance */
|
||||||
/* that correlates to the correct index */
|
/* 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;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the index */
|
/* more complex, and then you need to return the index */
|
||||||
/* that correlates to the correct instance number */
|
/* 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;
|
unsigned index = MAX_BINARY_OUTPUTS;
|
||||||
|
|
||||||
@@ -147,8 +149,8 @@ unsigned Binary_Output_Instance_To_Index(uint32_t object_instance)
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BACNET_BINARY_PV Binary_Output_Present_Value(uint32_t
|
static BACNET_BINARY_PV Binary_Output_Present_Value(
|
||||||
object_instance)
|
uint32_t object_instance)
|
||||||
{
|
{
|
||||||
BACNET_BINARY_PV value = RELINQUISH_DEFAULT;
|
BACNET_BINARY_PV value = RELINQUISH_DEFAULT;
|
||||||
unsigned index = 0;
|
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 */
|
/* 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 */
|
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 */
|
/* 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,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
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 len = 0;
|
||||||
int apdu_len = 0; /* return value */
|
int apdu_len = 0; /* return value */
|
||||||
BACNET_BIT_STRING bit_string;
|
BACNET_BIT_STRING bit_string;
|
||||||
BACNET_CHARACTER_STRING char_string;
|
BACNET_CHARACTER_STRING char_string;
|
||||||
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
||||||
@@ -200,116 +205,121 @@ int Binary_Output_Encode_Property_APDU(uint8_t * apdu,
|
|||||||
|
|
||||||
Binary_Output_Init();
|
Binary_Output_Init();
|
||||||
switch (property) {
|
switch (property) {
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
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)
|
|
||||||
apdu_len =
|
apdu_len =
|
||||||
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
|
encode_application_object_id(&apdu[0], OBJECT_BINARY_OUTPUT,
|
||||||
/* if no index was specified, then try to encode the entire list */
|
object_instance);
|
||||||
/* into one packet. */
|
break;
|
||||||
else if (array_index == BACNET_ARRAY_ALL) {
|
/* note: Name and Description don't have to be the same.
|
||||||
object_index =
|
You could make Description writable and different */
|
||||||
Binary_Output_Instance_To_Index(object_instance);
|
case PROP_OBJECT_NAME:
|
||||||
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
|
case PROP_DESCRIPTION:
|
||||||
/* FIXME: check if we have room before adding it to APDU */
|
characterstring_init_ansi(&char_string,
|
||||||
if (Binary_Output_Level[object_index][i] == BINARY_NULL)
|
Binary_Output_Name(object_instance));
|
||||||
len = encode_application_null(&apdu[apdu_len]);
|
apdu_len =
|
||||||
else {
|
encode_application_character_string(&apdu[0], &char_string);
|
||||||
present_value = Binary_Output_Level[object_index][i];
|
break;
|
||||||
len =
|
case PROP_OBJECT_TYPE:
|
||||||
encode_application_enumerated(&apdu[apdu_len],
|
apdu_len =
|
||||||
present_value);
|
encode_application_enumerated(&apdu[0], OBJECT_BINARY_OUTPUT);
|
||||||
}
|
break;
|
||||||
/* add it if we have room */
|
case PROP_PRESENT_VALUE:
|
||||||
if ((apdu_len + len) < MAX_APDU)
|
present_value = Binary_Output_Present_Value(object_instance);
|
||||||
apdu_len += len;
|
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
||||||
else {
|
break;
|
||||||
*error_class = ERROR_CLASS_SERVICES;
|
case PROP_STATUS_FLAGS:
|
||||||
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
/* note: see the details in the standard on how to use these */
|
||||||
apdu_len = -1;
|
bitstring_init(&bit_string);
|
||||||
break;
|
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);
|
||||||
} else {
|
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||||
object_index =
|
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||||
Binary_Output_Instance_To_Index(object_instance);
|
break;
|
||||||
if (array_index <= BACNET_MAX_PRIORITY) {
|
case PROP_EVENT_STATE:
|
||||||
if (Binary_Output_Level[object_index][array_index] ==
|
/* note: see the details in the standard on how to use this */
|
||||||
BINARY_NULL)
|
apdu_len =
|
||||||
len = encode_application_null(&apdu[apdu_len]);
|
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||||
else {
|
break;
|
||||||
present_value =
|
case PROP_OUT_OF_SERVICE:
|
||||||
Binary_Output_Level[object_index][array_index];
|
object_index = Binary_Output_Instance_To_Index(object_instance);
|
||||||
len =
|
state = Binary_Output_Out_Of_Service[object_index];
|
||||||
encode_application_enumerated(&apdu[apdu_len],
|
apdu_len = encode_application_boolean(&apdu[0], state);
|
||||||
present_value);
|
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 {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
object_index =
|
||||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
Binary_Output_Instance_To_Index(object_instance);
|
||||||
apdu_len = -1;
|
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;
|
break;
|
||||||
case PROP_RELINQUISH_DEFAULT:
|
case PROP_RELINQUISH_DEFAULT:
|
||||||
present_value = RELINQUISH_DEFAULT;
|
present_value = RELINQUISH_DEFAULT;
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*error_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
apdu_len = -1;
|
apdu_len = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns true if successful */
|
/* returns true if successful */
|
||||||
bool Binary_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Binary_Output_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code)
|
||||||
{
|
{
|
||||||
bool status = false; /* return value */
|
bool status = false; /* return value */
|
||||||
unsigned int object_index = 0;
|
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 < application_data_len: more data? */
|
||||||
/* FIXME: len == 0: unable to decode? */
|
/* FIXME: len == 0: unable to decode? */
|
||||||
switch (wp_data->object_property) {
|
switch (wp_data->object_property) {
|
||||||
case PROP_PRESENT_VALUE:
|
case PROP_PRESENT_VALUE:
|
||||||
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
|
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
|
||||||
priority = wp_data->priority;
|
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) {
|
|
||||||
/* Command priority 6 is reserved for use by Minimum On/Off
|
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||||
algorithm and may not be used for other purposes in any
|
algorithm and may not be used for other purposes in any
|
||||||
object. */
|
object. */
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
(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 {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*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) {
|
break;
|
||||||
level = BINARY_NULL;
|
case PROP_OUT_OF_SERVICE:
|
||||||
object_index =
|
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
|
||||||
Binary_Output_Instance_To_Index(wp_data->object_instance);
|
object_index =
|
||||||
priority = wp_data->priority;
|
Binary_Output_Instance_To_Index(wp_data->object_instance);
|
||||||
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
|
Binary_Output_Out_Of_Service[object_index] =
|
||||||
priority--;
|
value.type.Boolean;
|
||||||
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;
|
status = true;
|
||||||
} else {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*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_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||||
}
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -413,7 +423,8 @@ bool Binary_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void testBinaryOutput(Test * pTest)
|
void testBinaryOutput(
|
||||||
|
Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -428,8 +439,7 @@ void testBinaryOutput(Test * pTest)
|
|||||||
|
|
||||||
len = Binary_Output_Encode_Property_APDU(&apdu[0],
|
len = Binary_Output_Encode_Property_APDU(&apdu[0],
|
||||||
instance,
|
instance,
|
||||||
PROP_OBJECT_IDENTIFIER,
|
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
|
||||||
BACNET_ARRAY_ALL, &error_class, &error_code);
|
|
||||||
ct_test(pTest, len != 0);
|
ct_test(pTest, len != 0);
|
||||||
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
||||||
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
||||||
@@ -442,7 +452,8 @@ void testBinaryOutput(Test * pTest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST_BINARY_OUTPUT
|
#ifdef TEST_BINARY_OUTPUT
|
||||||
int main(void)
|
int main(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
Test *pTest;
|
Test *pTest;
|
||||||
bool rc;
|
bool rc;
|
||||||
@@ -459,5 +470,5 @@ int main(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* TEST_BINARY_INPUT */
|
#endif /* TEST_BINARY_INPUT */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|||||||
+188
-176
@@ -32,7 +32,7 @@
|
|||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
#include "config.h" /* the custom stuff */
|
#include "config.h" /* the custom stuff */
|
||||||
#include "wp.h"
|
#include "wp.h"
|
||||||
|
|
||||||
#define MAX_BINARY_VALUES 2
|
#define MAX_BINARY_VALUES 2
|
||||||
@@ -48,8 +48,7 @@ static BACNET_BINARY_PV
|
|||||||
static bool Binary_Value_Out_Of_Service[MAX_BINARY_VALUES];
|
static bool Binary_Value_Out_Of_Service[MAX_BINARY_VALUES];
|
||||||
|
|
||||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
/* 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_IDENTIFIER,
|
||||||
PROP_OBJECT_NAME,
|
PROP_OBJECT_NAME,
|
||||||
PROP_OBJECT_TYPE,
|
PROP_OBJECT_TYPE,
|
||||||
@@ -60,16 +59,14 @@ static const int Binary_Value_Properties_Required[] =
|
|||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Binary_Value_Properties_Optional[] =
|
static const int Binary_Value_Properties_Optional[] = {
|
||||||
{
|
|
||||||
PROP_DESCRIPTION,
|
PROP_DESCRIPTION,
|
||||||
PROP_PRIORITY_ARRAY,
|
PROP_PRIORITY_ARRAY,
|
||||||
PROP_RELINQUISH_DEFAULT,
|
PROP_RELINQUISH_DEFAULT,
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Binary_Value_Properties_Proprietary[] =
|
static const int Binary_Value_Properties_Proprietary[] = {
|
||||||
{
|
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,7 +85,8 @@ void Binary_Value_Property_Lists(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Binary_Value_Init(void)
|
void Binary_Value_Init(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
@@ -110,7 +108,8 @@ void Binary_Value_Init(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need validate that the */
|
/* more complex, and then you need validate that the */
|
||||||
/* given instance exists */
|
/* 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)
|
if (object_instance < MAX_BINARY_VALUES)
|
||||||
return true;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then count how many you have */
|
/* more complex, and then count how many you have */
|
||||||
unsigned Binary_Value_Count(void)
|
unsigned Binary_Value_Count(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
return MAX_BINARY_VALUES;
|
return MAX_BINARY_VALUES;
|
||||||
}
|
}
|
||||||
@@ -128,7 +128,8 @@ unsigned Binary_Value_Count(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the instance */
|
/* more complex, and then you need to return the instance */
|
||||||
/* that correlates to the correct index */
|
/* 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;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the index */
|
/* more complex, and then you need to return the index */
|
||||||
/* that correlates to the correct instance number */
|
/* 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;
|
unsigned index = MAX_BINARY_VALUES;
|
||||||
|
|
||||||
@@ -146,8 +148,8 @@ unsigned Binary_Value_Instance_To_Index(uint32_t object_instance)
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t
|
static BACNET_BINARY_PV Binary_Value_Present_Value(
|
||||||
object_instance)
|
uint32_t object_instance)
|
||||||
{
|
{
|
||||||
BACNET_BINARY_PV value = RELINQUISH_DEFAULT;
|
BACNET_BINARY_PV value = RELINQUISH_DEFAULT;
|
||||||
unsigned index = 0;
|
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 */
|
/* 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 */
|
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 */
|
/* 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,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
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 len = 0;
|
||||||
int apdu_len = 0; /* return value */
|
int apdu_len = 0; /* return value */
|
||||||
BACNET_BIT_STRING bit_string;
|
BACNET_BIT_STRING bit_string;
|
||||||
BACNET_CHARACTER_STRING char_string;
|
BACNET_CHARACTER_STRING char_string;
|
||||||
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
||||||
@@ -198,110 +203,116 @@ int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
|
|||||||
|
|
||||||
Binary_Value_Init();
|
Binary_Value_Init();
|
||||||
switch (property) {
|
switch (property) {
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
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)
|
|
||||||
apdu_len =
|
apdu_len =
|
||||||
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
|
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
|
||||||
/* if no index was specified, then try to encode the entire list */
|
object_instance);
|
||||||
/* into one packet. */
|
break;
|
||||||
else if (array_index == BACNET_ARRAY_ALL) {
|
/* 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);
|
object_index = Binary_Value_Instance_To_Index(object_instance);
|
||||||
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
|
state = Binary_Value_Out_Of_Service[object_index];
|
||||||
/* FIXME: check if we have room before adding it to APDU */
|
apdu_len = encode_application_boolean(&apdu[0], state);
|
||||||
if (Binary_Value_Level[object_index][i] == BINARY_NULL)
|
break;
|
||||||
len = encode_application_null(&apdu[apdu_len]);
|
case PROP_PRIORITY_ARRAY:
|
||||||
else {
|
/* Array element zero is the number of elements in the array */
|
||||||
present_value = Binary_Value_Level[object_index][i];
|
if (array_index == 0)
|
||||||
len =
|
apdu_len =
|
||||||
encode_application_enumerated(&apdu[apdu_len],
|
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
|
||||||
present_value);
|
/* if no index was specified, then try to encode the entire list */
|
||||||
}
|
/* into one packet. */
|
||||||
/* add it if we have room */
|
else if (array_index == BACNET_ARRAY_ALL) {
|
||||||
if ((apdu_len + len) < MAX_APDU)
|
object_index = Binary_Value_Instance_To_Index(object_instance);
|
||||||
apdu_len += len;
|
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
|
||||||
else {
|
/* FIXME: check if we have room before adding it to APDU */
|
||||||
*error_class = ERROR_CLASS_SERVICES;
|
if (Binary_Value_Level[object_index][i] == BINARY_NULL)
|
||||||
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
len = encode_application_null(&apdu[apdu_len]);
|
||||||
apdu_len = -1;
|
else {
|
||||||
break;
|
present_value = Binary_Value_Level[object_index][i];
|
||||||
}
|
len =
|
||||||
}
|
encode_application_enumerated(&apdu[apdu_len],
|
||||||
} else {
|
present_value);
|
||||||
object_index = Binary_Value_Instance_To_Index(object_instance);
|
}
|
||||||
if (array_index <= BACNET_MAX_PRIORITY) {
|
/* add it if we have room */
|
||||||
if (Binary_Value_Level[object_index][array_index] ==
|
if ((apdu_len + len) < MAX_APDU)
|
||||||
BINARY_NULL)
|
apdu_len += len;
|
||||||
len = encode_application_null(&apdu[apdu_len]);
|
else {
|
||||||
else {
|
*error_class = ERROR_CLASS_SERVICES;
|
||||||
present_value =
|
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
||||||
Binary_Value_Level[object_index][array_index];
|
apdu_len = -1;
|
||||||
len =
|
break;
|
||||||
encode_application_enumerated(&apdu[apdu_len],
|
}
|
||||||
present_value);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
object_index = Binary_Value_Instance_To_Index(object_instance);
|
||||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
if (array_index <= BACNET_MAX_PRIORITY) {
|
||||||
apdu_len = -1;
|
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;
|
break;
|
||||||
case PROP_RELINQUISH_DEFAULT:
|
case PROP_RELINQUISH_DEFAULT:
|
||||||
present_value = RELINQUISH_DEFAULT;
|
present_value = RELINQUISH_DEFAULT;
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*error_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
apdu_len = -1;
|
apdu_len = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns true if successful */
|
/* returns true if successful */
|
||||||
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Binary_Value_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code)
|
||||||
{
|
{
|
||||||
bool status = false; /* return value */
|
bool status = false; /* return value */
|
||||||
unsigned int object_index = 0;
|
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 < application_data_len: more data? */
|
||||||
/* FIXME: len == 0: unable to decode? */
|
/* FIXME: len == 0: unable to decode? */
|
||||||
switch (wp_data->object_property) {
|
switch (wp_data->object_property) {
|
||||||
case PROP_PRESENT_VALUE:
|
case PROP_PRESENT_VALUE:
|
||||||
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
|
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
|
||||||
priority = wp_data->priority;
|
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) {
|
|
||||||
/* Command priority 6 is reserved for use by Minimum On/Off
|
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||||
algorithm and may not be used for other purposes in any
|
algorithm and may not be used for other purposes in any
|
||||||
object. */
|
object. */
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
(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 {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*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) {
|
break;
|
||||||
level = BINARY_NULL;
|
case PROP_OUT_OF_SERVICE:
|
||||||
object_index =
|
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
|
||||||
Binary_Value_Instance_To_Index(wp_data->object_instance);
|
object_index =
|
||||||
priority = wp_data->priority;
|
Binary_Value_Instance_To_Index(wp_data->object_instance);
|
||||||
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
|
Binary_Value_Out_Of_Service[object_index] = value.type.Boolean;
|
||||||
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;
|
status = true;
|
||||||
} else {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*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_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||||
}
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -404,7 +415,8 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void testBinary_Value(Test * pTest)
|
void testBinary_Value(
|
||||||
|
Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -419,8 +431,7 @@ void testBinary_Value(Test * pTest)
|
|||||||
|
|
||||||
len = Binary_Value_Encode_Property_APDU(&apdu[0],
|
len = Binary_Value_Encode_Property_APDU(&apdu[0],
|
||||||
instance,
|
instance,
|
||||||
PROP_OBJECT_IDENTIFIER,
|
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
|
||||||
BACNET_ARRAY_ALL, &error_class, &error_code);
|
|
||||||
ct_test(pTest, len != 0);
|
ct_test(pTest, len != 0);
|
||||||
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
||||||
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
||||||
@@ -433,7 +444,8 @@ void testBinary_Value(Test * pTest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST_BINARY_VALUE
|
#ifdef TEST_BINARY_VALUE
|
||||||
int main(void)
|
int main(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
Test *pTest;
|
Test *pTest;
|
||||||
bool rc;
|
bool rc;
|
||||||
@@ -450,5 +462,5 @@ int main(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* TEST_BINARY_VALUE */
|
#endif /* TEST_BINARY_VALUE */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|||||||
+514
-429
File diff suppressed because it is too large
Load Diff
+610
-576
File diff suppressed because it is too large
Load Diff
+235
-208
@@ -32,7 +32,7 @@
|
|||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
#include "config.h" /* the custom stuff */
|
#include "config.h" /* the custom stuff */
|
||||||
#include "wp.h"
|
#include "wp.h"
|
||||||
|
|
||||||
#define MAX_LIGHTING_OUTPUTS 5
|
#define MAX_LIGHTING_OUTPUTS 5
|
||||||
@@ -49,12 +49,12 @@
|
|||||||
of the optional parameters, we represent them interally as
|
of the optional parameters, we represent them interally as
|
||||||
integers. */
|
integers. */
|
||||||
typedef struct LightingCommand {
|
typedef struct LightingCommand {
|
||||||
BACNET_LIGHTING_OPERATION operation;
|
BACNET_LIGHTING_OPERATION operation;
|
||||||
uint8_t level; /* 0..100 percent, 255=not used */
|
uint8_t level; /* 0..100 percent, 255=not used */
|
||||||
uint8_t ramp_rate; /* 0..100 percent-per-second, 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 */
|
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 fade_time; /* 1..65535 seconds to transition, 0=not used */
|
||||||
uint16_t duration; /* 1..65535 minutes until relinquish, 0=not used */
|
uint16_t duration; /* 1..65535 minutes until relinquish, 0=not used */
|
||||||
} BACNET_LIGHTING_COMMAND;
|
} BACNET_LIGHTING_COMMAND;
|
||||||
|
|
||||||
/* Here is our Priority Array. They are supposed to be Real, but */
|
/* 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 */
|
/* we need to have our arrays initialized before answering any calls */
|
||||||
static bool Lighting_Output_Initialized = false;
|
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)
|
BACNET_LIGHTING_COMMAND * data)
|
||||||
{
|
{
|
||||||
int apdu_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 */
|
int len = 0; /* total length of the apdu, return value */
|
||||||
float real_value = 0.0;
|
float real_value = 0.0;
|
||||||
uint32_t unsigned_value = 0;
|
uint32_t unsigned_value = 0;
|
||||||
|
|
||||||
if (apdu) {
|
if (apdu) {
|
||||||
len = encode_context_enumerated(&apdu[apdu_len], 0,
|
len = encode_context_enumerated(&apdu[apdu_len], 0, data->operation);
|
||||||
data->operation);
|
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
/* optional level? */
|
/* optional level? */
|
||||||
if (data->level != 255) {
|
if (data->level != 255) {
|
||||||
real_value = data->level;
|
real_value = data->level;
|
||||||
len = encode_context_real(&apdu[apdu_len], 1,
|
len = encode_context_real(&apdu[apdu_len], 1, real_value);
|
||||||
real_value);
|
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
}
|
}
|
||||||
/* optional ramp-rate */
|
/* optional ramp-rate */
|
||||||
if (data->ramp_rate != 255) {
|
if (data->ramp_rate != 255) {
|
||||||
real_value = data->ramp_rate;
|
real_value = data->ramp_rate;
|
||||||
len = encode_context_real(&apdu[apdu_len], 2,
|
len = encode_context_real(&apdu[apdu_len], 2, real_value);
|
||||||
real_value);
|
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
}
|
}
|
||||||
/* optional step increment */
|
/* optional step increment */
|
||||||
if (data->step_increment != 255) {
|
if (data->step_increment != 255) {
|
||||||
real_value = data->step_increment;
|
real_value = data->step_increment;
|
||||||
len = encode_context_real(&apdu[apdu_len], 3,
|
len = encode_context_real(&apdu[apdu_len], 3, real_value);
|
||||||
real_value);
|
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
}
|
}
|
||||||
/* optional fade time */
|
/* optional fade time */
|
||||||
if (data->fade_time != 0) {
|
if (data->fade_time != 0) {
|
||||||
real_value = data->fade_time;
|
real_value = data->fade_time;
|
||||||
len = encode_context_real(&apdu[apdu_len], 4,
|
len = encode_context_real(&apdu[apdu_len], 4, real_value);
|
||||||
real_value);
|
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
}
|
}
|
||||||
/* optional duration */
|
/* optional duration */
|
||||||
if (data->duration != 0) {
|
if (data->duration != 0) {
|
||||||
unsigned_value = data->duration;
|
unsigned_value = data->duration;
|
||||||
len = encode_context_unsigned(&apdu[apdu_len], 5,
|
len = encode_context_unsigned(&apdu[apdu_len], 5, unsigned_value);
|
||||||
unsigned_value);
|
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,18 +123,20 @@ int Lighting_Output_Encode_Lighting_Command(uint8_t * apdu,
|
|||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Lighting_Output_Decode_Lighting_Command(uint8_t * apdu,
|
int Lighting_Output_Decode_Lighting_Command(
|
||||||
unsigned apdu_max_len, BACNET_LIGHTING_COMMAND * data)
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_max_len,
|
||||||
|
BACNET_LIGHTING_COMMAND * data)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int apdu_len = 0;
|
int apdu_len = 0;
|
||||||
int tag_len = 0;
|
int tag_len = 0;
|
||||||
uint8_t tag_number = 0;
|
uint8_t tag_number = 0;
|
||||||
uint32_t len_value_type = 0;
|
uint32_t len_value_type = 0;
|
||||||
int type = 0; /* for decoding */
|
int type = 0; /* for decoding */
|
||||||
int property = 0; /* for decoding */
|
int property = 0; /* for decoding */
|
||||||
uint32_t unsigned_value = 0;
|
uint32_t unsigned_value = 0;
|
||||||
int i = 0; /* loop counter */
|
int i = 0; /* loop counter */
|
||||||
float real_value = 0.0;
|
float real_value = 0.0;
|
||||||
|
|
||||||
/* check for value pointers */
|
/* 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],
|
len = decode_tag_number_and_value(&apdu[apdu_len],
|
||||||
&tag_number, &len_value_type);
|
&tag_number, &len_value_type);
|
||||||
apdu_len += len;
|
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;
|
apdu_len += len;
|
||||||
/* Tag 1: level - OPTIONAL */
|
/* Tag 1: level - OPTIONAL */
|
||||||
if (decode_is_context_tag(&apdu[apdu_len], 1)) {
|
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;
|
unsigned i, j;
|
||||||
|
|
||||||
@@ -197,7 +197,8 @@ void Lighting_Output_Init(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need validate that the */
|
/* more complex, and then you need validate that the */
|
||||||
/* given instance exists */
|
/* given instance exists */
|
||||||
bool Lighting_Output_Valid_Instance(uint32_t object_instance)
|
bool Lighting_Output_Valid_Instance(
|
||||||
|
uint32_t object_instance)
|
||||||
{
|
{
|
||||||
Lighting_Output_Init();
|
Lighting_Output_Init();
|
||||||
if (object_instance < MAX_LIGHTING_OUTPUTS)
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then count how many you have */
|
/* more complex, and then count how many you have */
|
||||||
unsigned Lighting_Output_Count(void)
|
unsigned Lighting_Output_Count(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
Lighting_Output_Init();
|
Lighting_Output_Init();
|
||||||
return MAX_LIGHTING_OUTPUTS;
|
return MAX_LIGHTING_OUTPUTS;
|
||||||
@@ -217,7 +219,8 @@ unsigned Lighting_Output_Count(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the instance */
|
/* more complex, and then you need to return the instance */
|
||||||
/* that correlates to the correct index */
|
/* 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();
|
Lighting_Output_Init();
|
||||||
return index;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the index */
|
/* more complex, and then you need to return the index */
|
||||||
/* that correlates to the correct instance number */
|
/* 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;
|
unsigned index = MAX_LIGHTING_OUTPUTS;
|
||||||
|
|
||||||
@@ -237,7 +241,8 @@ unsigned Lighting_Output_Instance_To_Index(uint32_t object_instance)
|
|||||||
return index;
|
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;
|
float value = LIGHTING_RELINQUISH_DEFAULT;
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
@@ -257,10 +262,11 @@ float Lighting_Output_Present_Value(uint32_t object_instance)
|
|||||||
return value;
|
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 index = 0; /* instance to index conversion */
|
||||||
unsigned i = 0; /* loop counter */
|
unsigned i = 0; /* loop counter */
|
||||||
unsigned priority = 0; /* return value */
|
unsigned priority = 0; /* return value */
|
||||||
|
|
||||||
Lighting_Output_Init();
|
Lighting_Output_Init();
|
||||||
@@ -277,8 +283,10 @@ unsigned Lighting_Output_Present_Value_Priority(uint32_t object_instance)
|
|||||||
return priority;
|
return priority;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Lighting_Output_Present_Value_Set(uint32_t object_instance,
|
bool Lighting_Output_Present_Value_Set(
|
||||||
float value, unsigned priority)
|
uint32_t object_instance,
|
||||||
|
float value,
|
||||||
|
unsigned priority)
|
||||||
{
|
{
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
bool status = false;
|
bool status = false;
|
||||||
@@ -288,7 +296,7 @@ bool Lighting_Output_Present_Value_Set(uint32_t object_instance,
|
|||||||
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||||
(priority != 6 /* reserved */ ) &&
|
(priority != 6 /* reserved */ ) &&
|
||||||
(value >= 0.0) && (value <= 100.0)) {
|
(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
|
/* Note: you could set the physical output here to the next
|
||||||
highest priority, or to the relinquish default if no
|
highest priority, or to the relinquish default if no
|
||||||
priorities are set.
|
priorities are set.
|
||||||
@@ -302,7 +310,8 @@ bool Lighting_Output_Present_Value_Set(uint32_t object_instance,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Lighting_Output_Present_Value_Relinquish(uint32_t object_instance,
|
bool Lighting_Output_Present_Value_Relinquish(
|
||||||
|
uint32_t object_instance,
|
||||||
int priority)
|
int priority)
|
||||||
{
|
{
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
@@ -312,7 +321,7 @@ bool Lighting_Output_Present_Value_Relinquish(uint32_t object_instance,
|
|||||||
if (index < MAX_LIGHTING_OUTPUTS) {
|
if (index < MAX_LIGHTING_OUTPUTS) {
|
||||||
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||||
(priority != 6 /* reserved */ )) {
|
(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
|
/* Note: you could set the physical output here to the next
|
||||||
highest priority, or to the relinquish default if no
|
highest priority, or to the relinquish default if no
|
||||||
priorities are set.
|
priorities are set.
|
||||||
@@ -326,7 +335,8 @@ bool Lighting_Output_Present_Value_Relinquish(uint32_t object_instance,
|
|||||||
return status;
|
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;
|
float value = LIGHTING_RELINQUISH_DEFAULT;
|
||||||
unsigned index = 0;
|
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 */
|
/* 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 */
|
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 */
|
/* 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,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
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 len = 0;
|
||||||
int apdu_len = 0; /* return value */
|
int apdu_len = 0; /* return value */
|
||||||
BACNET_BIT_STRING bit_string;
|
BACNET_BIT_STRING bit_string;
|
||||||
BACNET_CHARACTER_STRING char_string;
|
BACNET_CHARACTER_STRING char_string;
|
||||||
float real_value = (float) 1.414;
|
float real_value = (float) 1.414;
|
||||||
@@ -371,118 +384,129 @@ int Lighting_Output_Encode_Property_APDU(uint8_t * apdu,
|
|||||||
|
|
||||||
Lighting_Output_Init();
|
Lighting_Output_Init();
|
||||||
switch (property) {
|
switch (property) {
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
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)
|
|
||||||
apdu_len =
|
apdu_len =
|
||||||
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
|
encode_application_object_id(&apdu[0], OBJECT_LIGHTING_OUTPUT,
|
||||||
/* if no index was specified, then try to encode the entire list */
|
object_instance);
|
||||||
/* into one packet. */
|
break;
|
||||||
else if (array_index == BACNET_ARRAY_ALL) {
|
case PROP_OBJECT_NAME:
|
||||||
object_index =
|
case PROP_DESCRIPTION:
|
||||||
Lighting_Output_Instance_To_Index(object_instance);
|
/* object name must be unique in this device. */
|
||||||
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
|
/* FIXME: description could be writable and different than object name */
|
||||||
/* FIXME: check if we have room before adding it to APDU */
|
characterstring_init_ansi(&char_string,
|
||||||
if (Lighting_Output_Level[object_index][i] == LIGHTING_LEVEL_NULL)
|
Lighting_Output_Name(object_instance));
|
||||||
len = encode_application_null(&apdu[apdu_len]);
|
apdu_len =
|
||||||
else {
|
encode_application_character_string(&apdu[0], &char_string);
|
||||||
real_value = Lighting_Output_Level[object_index][i];
|
break;
|
||||||
len = encode_application_real(&apdu[apdu_len], real_value);
|
case PROP_OBJECT_TYPE:
|
||||||
}
|
apdu_len =
|
||||||
/* add it if we have room */
|
encode_application_enumerated(&apdu[0],
|
||||||
if ((apdu_len + len) < MAX_APDU)
|
OBJECT_LIGHTING_OUTPUT);
|
||||||
apdu_len += len;
|
break;
|
||||||
else {
|
case PROP_PRESENT_VALUE:
|
||||||
*error_class = ERROR_CLASS_SERVICES;
|
real_value = Lighting_Output_Present_Value(object_instance);
|
||||||
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
apdu_len = encode_application_real(&apdu[0], real_value);
|
||||||
apdu_len = -1;
|
break;
|
||||||
break;
|
case PROP_PROGRESS_VALUE:
|
||||||
}
|
real_value = Lighting_Output_Progress_Value(object_instance);
|
||||||
}
|
apdu_len = encode_application_real(&apdu[0], real_value);
|
||||||
} else {
|
break;
|
||||||
object_index =
|
case PROP_LIGHTING_COMMAND:
|
||||||
Lighting_Output_Instance_To_Index(object_instance);
|
apdu_len = Lighting_Output_Encode_Lighting_Command(&apdu[0],
|
||||||
if (array_index <= BACNET_MAX_PRIORITY) {
|
&Lighting_Command[object_instance]);
|
||||||
if (Lighting_Output_Level[object_index][array_index - 1] ==
|
break;
|
||||||
LIGHTING_LEVEL_NULL)
|
case PROP_STATUS_FLAGS:
|
||||||
apdu_len = encode_application_null(&apdu[0]);
|
bitstring_init(&bit_string);
|
||||||
else {
|
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||||
real_value =
|
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||||
Lighting_Output_Level[object_index][array_index - 1];
|
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||||
apdu_len = encode_application_real(&apdu[0], real_value);
|
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 {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
object_index =
|
||||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
Lighting_Output_Instance_To_Index(object_instance);
|
||||||
apdu_len = -1;
|
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;
|
break;
|
||||||
case PROP_RELINQUISH_DEFAULT:
|
case PROP_RELINQUISH_DEFAULT:
|
||||||
real_value = LIGHTING_RELINQUISH_DEFAULT;
|
real_value = LIGHTING_RELINQUISH_DEFAULT;
|
||||||
apdu_len = encode_application_real(&apdu[0], real_value);
|
apdu_len = encode_application_real(&apdu[0], real_value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*error_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
apdu_len = -1;
|
apdu_len = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns true if successful */
|
/* returns true if successful */
|
||||||
bool Lighting_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Lighting_Output_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code)
|
||||||
{
|
{
|
||||||
bool status = false; /* return value */
|
bool status = false; /* return value */
|
||||||
unsigned int object_index = 0;
|
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 < application_data_len: more data? */
|
||||||
/* FIXME: len == 0: unable to decode? */
|
/* FIXME: len == 0: unable to decode? */
|
||||||
switch (wp_data->object_property) {
|
switch (wp_data->object_property) {
|
||||||
case PROP_PRESENT_VALUE:
|
case PROP_PRESENT_VALUE:
|
||||||
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
|
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
|
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||||
algorithm and may not be used for other purposes in any
|
algorithm and may not be used for other purposes in any
|
||||||
object. */
|
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_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||||
} else if (!status) {
|
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
|
||||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
|
||||||
}
|
}
|
||||||
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
|
break;
|
||||||
level = LIGHTING_LEVEL_NULL;
|
case PROP_LIGHTING_COMMAND:
|
||||||
object_index =
|
/* FIXME: error checking? */
|
||||||
Lighting_Output_Instance_To_Index(wp_data->object_instance);
|
Lighting_Output_Decode_Lighting_Command(wp_data->application_data,
|
||||||
status =
|
wp_data->application_data_len,
|
||||||
Lighting_Output_Present_Value_Relinquish(wp_data->
|
&Lighting_Command[wp_data->object_instance]);
|
||||||
object_instance, wp_data->priority);
|
break;
|
||||||
if (wp_data->priority == 6) {
|
case PROP_OUT_OF_SERVICE:
|
||||||
/* Command priority 6 is reserved for use by Minimum On/Off
|
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
|
||||||
algorithm and may not be used for other purposes in any
|
object_index =
|
||||||
object. */
|
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_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||||
} else if (!status) {
|
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
|
||||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
|
default:
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*error_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||||
}
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -575,7 +601,8 @@ bool Lighting_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void testLightingOutput(Test * pTest)
|
void testLightingOutput(
|
||||||
|
Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -590,8 +617,7 @@ void testLightingOutput(Test * pTest)
|
|||||||
|
|
||||||
len = Lighting_Output_Encode_Property_APDU(&apdu[0],
|
len = Lighting_Output_Encode_Property_APDU(&apdu[0],
|
||||||
instance,
|
instance,
|
||||||
PROP_OBJECT_IDENTIFIER,
|
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
|
||||||
BACNET_ARRAY_ALL, &error_class, &error_code);
|
|
||||||
ct_test(pTest, len != 0);
|
ct_test(pTest, len != 0);
|
||||||
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
||||||
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
||||||
@@ -604,7 +630,8 @@ void testLightingOutput(Test * pTest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST_LIGHTING_OUTPUT
|
#ifdef TEST_LIGHTING_OUTPUT
|
||||||
int main(void)
|
int main(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
Test *pTest;
|
Test *pTest;
|
||||||
bool rc;
|
bool rc;
|
||||||
@@ -621,5 +648,5 @@ int main(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* TEST_LIGHTING_INPUT */
|
#endif /* TEST_LIGHTING_INPUT */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|||||||
+139
-131
@@ -32,14 +32,13 @@
|
|||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
#include "config.h" /* the custom stuff */
|
#include "config.h" /* the custom stuff */
|
||||||
#include "wp.h"
|
#include "wp.h"
|
||||||
|
|
||||||
#define MAX_LIFE_SAFETY_POINTS 7
|
#define MAX_LIFE_SAFETY_POINTS 7
|
||||||
|
|
||||||
/* Here are our stored levels.*/
|
/* Here are our stored levels.*/
|
||||||
static BACNET_LIFE_SAFETY_MODE
|
static BACNET_LIFE_SAFETY_MODE Life_Safety_Point_Mode[MAX_LIFE_SAFETY_POINTS];
|
||||||
Life_Safety_Point_Mode[MAX_LIFE_SAFETY_POINTS];
|
|
||||||
static BACNET_LIFE_SAFETY_STATE
|
static BACNET_LIFE_SAFETY_STATE
|
||||||
Life_Safety_Point_State[MAX_LIFE_SAFETY_POINTS];
|
Life_Safety_Point_State[MAX_LIFE_SAFETY_POINTS];
|
||||||
static BACNET_SILENCED_STATE
|
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];
|
static bool Life_Safety_Point_Out_Of_Service[MAX_LIFE_SAFETY_POINTS];
|
||||||
|
|
||||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
/* 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_IDENTIFIER,
|
||||||
PROP_OBJECT_NAME,
|
PROP_OBJECT_NAME,
|
||||||
PROP_OBJECT_TYPE,
|
PROP_OBJECT_TYPE,
|
||||||
@@ -68,14 +66,12 @@ static const int Life_Safety_Point_Properties_Required[] =
|
|||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Life_Safety_Point_Properties_Optional[] =
|
static const int Life_Safety_Point_Properties_Optional[] = {
|
||||||
{
|
|
||||||
PROP_DESCRIPTION,
|
PROP_DESCRIPTION,
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Life_Safety_Point_Properties_Proprietary[] =
|
static const int Life_Safety_Point_Properties_Proprietary[] = {
|
||||||
{
|
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -94,7 +90,8 @@ void Life_Safety_Point_Property_Lists(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Life_Safety_Point_Init(void)
|
void Life_Safety_Point_Init(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
@@ -106,8 +103,7 @@ void Life_Safety_Point_Init(void)
|
|||||||
for (i = 0; i < MAX_LIFE_SAFETY_POINTS; i++) {
|
for (i = 0; i < MAX_LIFE_SAFETY_POINTS; i++) {
|
||||||
Life_Safety_Point_Mode[i] = LIFE_SAFETY_MODE_DEFAULT;
|
Life_Safety_Point_Mode[i] = LIFE_SAFETY_MODE_DEFAULT;
|
||||||
Life_Safety_Point_State[i] = LIFE_SAFETY_STATE_QUIET;
|
Life_Safety_Point_State[i] = LIFE_SAFETY_STATE_QUIET;
|
||||||
Life_Safety_Point_Silenced_State[i] =
|
Life_Safety_Point_Silenced_State[i] = SILENCED_STATE_UNSILENCED;
|
||||||
SILENCED_STATE_UNSILENCED;
|
|
||||||
Life_Safety_Point_Operation[i] = LIFE_SAFETY_OPERATION_NONE;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need validate that the */
|
/* more complex, and then you need validate that the */
|
||||||
/* given instance exists */
|
/* 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();
|
Life_Safety_Point_Init();
|
||||||
if (object_instance < MAX_LIFE_SAFETY_POINTS)
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then count how many you have */
|
/* 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();
|
Life_Safety_Point_Init();
|
||||||
return MAX_LIFE_SAFETY_POINTS;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the instance */
|
/* more complex, and then you need to return the instance */
|
||||||
/* that correlates to the correct index */
|
/* 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();
|
Life_Safety_Point_Init();
|
||||||
return index;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the index */
|
/* more complex, and then you need to return the index */
|
||||||
/* that correlates to the correct instance number */
|
/* 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;
|
unsigned index = MAX_LIFE_SAFETY_POINTS;
|
||||||
|
|
||||||
@@ -158,8 +158,8 @@ unsigned Life_Safety_Point_Instance_To_Index(uint32_t object_instance)
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BACNET_LIFE_SAFETY_STATE Life_Safety_Point_Present_Value(uint32_t
|
static BACNET_LIFE_SAFETY_STATE Life_Safety_Point_Present_Value(
|
||||||
object_instance)
|
uint32_t object_instance)
|
||||||
{
|
{
|
||||||
BACNET_LIFE_SAFETY_STATE present_value = LIFE_SAFETY_STATE_QUIET;
|
BACNET_LIFE_SAFETY_STATE present_value = LIFE_SAFETY_STATE_QUIET;
|
||||||
unsigned index = 0;
|
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 */
|
/* 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 */
|
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 */
|
/* 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,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
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 len = 0;
|
||||||
int apdu_len = 0; /* return value */
|
int apdu_len = 0; /* return value */
|
||||||
BACNET_BIT_STRING bit_string;
|
BACNET_BIT_STRING bit_string;
|
||||||
BACNET_CHARACTER_STRING char_string;
|
BACNET_CHARACTER_STRING char_string;
|
||||||
BACNET_LIFE_SAFETY_STATE present_value = LIFE_SAFETY_STATE_QUIET;
|
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;
|
bool state = false;
|
||||||
BACNET_RELIABILITY reliability = RELIABILITY_NO_FAULT_DETECTED;
|
BACNET_RELIABILITY reliability = RELIABILITY_NO_FAULT_DETECTED;
|
||||||
|
|
||||||
(void) array_index; /* currently not used */
|
(void) array_index; /* currently not used */
|
||||||
Life_Safety_Point_Init();
|
Life_Safety_Point_Init();
|
||||||
switch (property) {
|
switch (property) {
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
case PROP_OBJECT_IDENTIFIER:
|
||||||
apdu_len =
|
apdu_len =
|
||||||
encode_application_object_id(&apdu[0], OBJECT_LIFE_SAFETY_POINT,
|
encode_application_object_id(&apdu[0],
|
||||||
object_instance);
|
OBJECT_LIFE_SAFETY_POINT, object_instance);
|
||||||
break;
|
break;
|
||||||
case PROP_OBJECT_NAME:
|
case PROP_OBJECT_NAME:
|
||||||
case PROP_DESCRIPTION:
|
case PROP_DESCRIPTION:
|
||||||
characterstring_init_ansi(&char_string,
|
characterstring_init_ansi(&char_string,
|
||||||
Life_Safety_Point_Name(object_instance));
|
Life_Safety_Point_Name(object_instance));
|
||||||
apdu_len = encode_application_character_string(&apdu[0], &char_string);
|
apdu_len =
|
||||||
break;
|
encode_application_character_string(&apdu[0], &char_string);
|
||||||
case PROP_OBJECT_TYPE:
|
break;
|
||||||
apdu_len =
|
case PROP_OBJECT_TYPE:
|
||||||
encode_application_enumerated(&apdu[0], OBJECT_LIFE_SAFETY_POINT);
|
apdu_len =
|
||||||
break;
|
encode_application_enumerated(&apdu[0],
|
||||||
case PROP_PRESENT_VALUE:
|
OBJECT_LIFE_SAFETY_POINT);
|
||||||
present_value = Life_Safety_Point_Present_Value(object_instance);
|
break;
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
case PROP_PRESENT_VALUE:
|
||||||
break;
|
present_value = Life_Safety_Point_Present_Value(object_instance);
|
||||||
case PROP_STATUS_FLAGS:
|
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
||||||
bitstring_init(&bit_string);
|
break;
|
||||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
case PROP_STATUS_FLAGS:
|
||||||
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
bitstring_init(&bit_string);
|
||||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||||
break;
|
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||||
case PROP_EVENT_STATE:
|
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
break;
|
||||||
break;
|
case PROP_EVENT_STATE:
|
||||||
case PROP_OUT_OF_SERVICE:
|
apdu_len =
|
||||||
object_index =
|
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||||
Life_Safety_Point_Instance_To_Index(object_instance);
|
break;
|
||||||
state = Life_Safety_Point_Out_Of_Service[object_index];
|
case PROP_OUT_OF_SERVICE:
|
||||||
apdu_len = encode_application_boolean(&apdu[0], state);
|
object_index =
|
||||||
break;
|
Life_Safety_Point_Instance_To_Index(object_instance);
|
||||||
case PROP_RELIABILITY:
|
state = Life_Safety_Point_Out_Of_Service[object_index];
|
||||||
/* see standard for details about this property */
|
apdu_len = encode_application_boolean(&apdu[0], state);
|
||||||
reliability = RELIABILITY_NO_FAULT_DETECTED;
|
break;
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], reliability);
|
case PROP_RELIABILITY:
|
||||||
break;
|
/* see standard for details about this property */
|
||||||
case PROP_MODE:
|
reliability = RELIABILITY_NO_FAULT_DETECTED;
|
||||||
object_index =
|
apdu_len = encode_application_enumerated(&apdu[0], reliability);
|
||||||
Life_Safety_Point_Instance_To_Index(object_instance);
|
break;
|
||||||
mode = Life_Safety_Point_Mode[object_index];
|
case PROP_MODE:
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], mode);
|
object_index =
|
||||||
break;
|
Life_Safety_Point_Instance_To_Index(object_instance);
|
||||||
case PROP_ACCEPTED_MODES:
|
mode = Life_Safety_Point_Mode[object_index];
|
||||||
for (mode = MIN_LIFE_SAFETY_MODE; mode < MAX_LIFE_SAFETY_MODE;
|
apdu_len = encode_application_enumerated(&apdu[0], mode);
|
||||||
mode++) {
|
break;
|
||||||
len = encode_application_enumerated(&apdu[apdu_len], mode);
|
case PROP_ACCEPTED_MODES:
|
||||||
apdu_len += len;
|
for (mode = MIN_LIFE_SAFETY_MODE; mode < MAX_LIFE_SAFETY_MODE;
|
||||||
}
|
mode++) {
|
||||||
break;
|
len = encode_application_enumerated(&apdu[apdu_len], mode);
|
||||||
case PROP_SILENCED:
|
apdu_len += len;
|
||||||
object_index =
|
}
|
||||||
Life_Safety_Point_Instance_To_Index(object_instance);
|
break;
|
||||||
silenced_state = Life_Safety_Point_Silenced_State[object_index];
|
case PROP_SILENCED:
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], silenced_state);
|
object_index =
|
||||||
break;
|
Life_Safety_Point_Instance_To_Index(object_instance);
|
||||||
case PROP_OPERATION_EXPECTED:
|
silenced_state = Life_Safety_Point_Silenced_State[object_index];
|
||||||
object_index =
|
apdu_len = encode_application_enumerated(&apdu[0], silenced_state);
|
||||||
Life_Safety_Point_Instance_To_Index(object_instance);
|
break;
|
||||||
operation = Life_Safety_Point_Operation[object_index];
|
case PROP_OPERATION_EXPECTED:
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], operation);
|
object_index =
|
||||||
break;
|
Life_Safety_Point_Instance_To_Index(object_instance);
|
||||||
default:
|
operation = Life_Safety_Point_Operation[object_index];
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
apdu_len = encode_application_enumerated(&apdu[0], operation);
|
||||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
break;
|
||||||
apdu_len = -1;
|
default:
|
||||||
break;
|
*error_class = ERROR_CLASS_PROPERTY;
|
||||||
|
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
|
apdu_len = -1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns true if successful */
|
/* returns true if successful */
|
||||||
bool Life_Safety_Point_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Life_Safety_Point_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code)
|
||||||
{
|
{
|
||||||
bool status = false; /* return value */
|
bool status = false; /* return value */
|
||||||
unsigned int object_index = 0;
|
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 < application_data_len: more data? */
|
||||||
/* FIXME: len == 0: unable to decode? */
|
/* FIXME: len == 0: unable to decode? */
|
||||||
switch (wp_data->object_property) {
|
switch (wp_data->object_property) {
|
||||||
case PROP_MODE:
|
case PROP_MODE:
|
||||||
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
|
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
|
||||||
if ((value.type.Enumerated >= MIN_LIFE_SAFETY_MODE) &&
|
if ((value.type.Enumerated >= MIN_LIFE_SAFETY_MODE) &&
|
||||||
(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 =
|
object_index =
|
||||||
Life_Safety_Point_Instance_To_Index(wp_data->
|
Life_Safety_Point_Instance_To_Index(wp_data->
|
||||||
object_instance);
|
object_instance);
|
||||||
Life_Safety_Point_Mode[object_index] =
|
Life_Safety_Point_Out_Of_Service[object_index] =
|
||||||
value.type.Enumerated;
|
value.type.Boolean;
|
||||||
status = true;
|
status = true;
|
||||||
} else {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*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_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||||
}
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -351,7 +359,8 @@ bool Life_Safety_Point_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void testLifeSafetyPoint(Test * pTest)
|
void testLifeSafetyPoint(
|
||||||
|
Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -366,8 +375,7 @@ void testLifeSafetyPoint(Test * pTest)
|
|||||||
|
|
||||||
len = Life_Safety_Point_Encode_Property_APDU(&apdu[0],
|
len = Life_Safety_Point_Encode_Property_APDU(&apdu[0],
|
||||||
instance,
|
instance,
|
||||||
PROP_OBJECT_IDENTIFIER,
|
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
|
||||||
BACNET_ARRAY_ALL, &error_class, &error_code);
|
|
||||||
ct_test(pTest, len != 0);
|
ct_test(pTest, len != 0);
|
||||||
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
||||||
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
||||||
@@ -380,7 +388,8 @@ void testLifeSafetyPoint(Test * pTest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST_LIFE_SAFETY_POINT
|
#ifdef TEST_LIFE_SAFETY_POINT
|
||||||
int main(void)
|
int main(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
Test *pTest;
|
Test *pTest;
|
||||||
bool rc;
|
bool rc;
|
||||||
@@ -397,6 +406,5 @@ int main(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* TEST_LIFE_SAFETY_POINT */
|
#endif /* TEST_LIFE_SAFETY_POINT */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|
||||||
|
|||||||
+202
-189
@@ -32,7 +32,7 @@
|
|||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
#include "config.h" /* the custom stuff */
|
#include "config.h" /* the custom stuff */
|
||||||
#include "wp.h"
|
#include "wp.h"
|
||||||
|
|
||||||
#define MAX_MULTISTATE_OUTPUTS 4
|
#define MAX_MULTISTATE_OUTPUTS 4
|
||||||
@@ -53,8 +53,7 @@ static uint8_t
|
|||||||
static bool Multistate_Output_Out_Of_Service[MAX_MULTISTATE_OUTPUTS];
|
static bool Multistate_Output_Out_Of_Service[MAX_MULTISTATE_OUTPUTS];
|
||||||
|
|
||||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
/* 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_IDENTIFIER,
|
||||||
PROP_OBJECT_NAME,
|
PROP_OBJECT_NAME,
|
||||||
PROP_OBJECT_TYPE,
|
PROP_OBJECT_TYPE,
|
||||||
@@ -68,14 +67,12 @@ static const int Multistate_Output_Properties_Required[] =
|
|||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Multistate_Output_Properties_Optional[] =
|
static const int Multistate_Output_Properties_Optional[] = {
|
||||||
{
|
|
||||||
PROP_DESCRIPTION,
|
PROP_DESCRIPTION,
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int Multistate_Output_Properties_Proprietary[] =
|
static const int Multistate_Output_Properties_Proprietary[] = {
|
||||||
{
|
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -94,7 +91,8 @@ void Multistate_Output_Property_Lists(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Multistate_Output_Init(void)
|
void Multistate_Output_Init(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
unsigned i, j;
|
unsigned i, j;
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
@@ -116,7 +114,8 @@ void Multistate_Output_Init(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need validate that the */
|
/* more complex, and then you need validate that the */
|
||||||
/* given instance exists */
|
/* 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)
|
if (object_instance < MAX_MULTISTATE_OUTPUTS)
|
||||||
return true;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then count how many you have */
|
/* more complex, and then count how many you have */
|
||||||
unsigned Multistate_Output_Count(void)
|
unsigned Multistate_Output_Count(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
return MAX_MULTISTATE_OUTPUTS;
|
return MAX_MULTISTATE_OUTPUTS;
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,8 @@ unsigned Multistate_Output_Count(void)
|
|||||||
/* we simply have 0-n object instances. Yours might be */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the instance */
|
/* more complex, and then you need to return the instance */
|
||||||
/* that correlates to the correct index */
|
/* 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;
|
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 */
|
/* we simply have 0-n object instances. Yours might be */
|
||||||
/* more complex, and then you need to return the index */
|
/* more complex, and then you need to return the index */
|
||||||
/* that correlates to the correct instance number */
|
/* 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;
|
unsigned index = MAX_MULTISTATE_OUTPUTS;
|
||||||
|
|
||||||
@@ -152,7 +154,8 @@ unsigned Multistate_Output_Instance_To_Index(uint32_t object_instance)
|
|||||||
return index;
|
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;
|
uint32_t value = MULTISTATE_RELINQUISH_DEFAULT;
|
||||||
unsigned index = 0;
|
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 */
|
/* 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 */
|
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 */
|
/* 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,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
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 len = 0;
|
||||||
int apdu_len = 0; /* return value */
|
int apdu_len = 0; /* return value */
|
||||||
BACNET_BIT_STRING bit_string;
|
BACNET_BIT_STRING bit_string;
|
||||||
BACNET_CHARACTER_STRING char_string;
|
BACNET_CHARACTER_STRING char_string;
|
||||||
uint32_t present_value = 0;
|
uint32_t present_value = 0;
|
||||||
@@ -203,122 +209,128 @@ int Multistate_Output_Encode_Property_APDU(uint8_t * apdu,
|
|||||||
|
|
||||||
Multistate_Output_Init();
|
Multistate_Output_Init();
|
||||||
switch (property) {
|
switch (property) {
|
||||||
case PROP_OBJECT_IDENTIFIER:
|
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)
|
|
||||||
apdu_len =
|
apdu_len =
|
||||||
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
|
encode_application_object_id(&apdu[0],
|
||||||
/* if no index was specified, then try to encode the entire list */
|
OBJECT_MULTI_STATE_OUTPUT, object_instance);
|
||||||
/* into one packet. */
|
break;
|
||||||
else if (array_index == BACNET_ARRAY_ALL) {
|
/* 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 =
|
object_index =
|
||||||
Multistate_Output_Instance_To_Index(object_instance);
|
Multistate_Output_Instance_To_Index(object_instance);
|
||||||
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
|
state = Multistate_Output_Out_Of_Service[object_index];
|
||||||
/* FIXME: check if we have room before adding it to APDU */
|
apdu_len = encode_application_boolean(&apdu[0], state);
|
||||||
if (Multistate_Output_Level[object_index][i] ==
|
break;
|
||||||
MULTISTATE_NULL)
|
case PROP_PRIORITY_ARRAY:
|
||||||
len = encode_application_null(&apdu[apdu_len]);
|
/* Array element zero is the number of elements in the array */
|
||||||
else {
|
if (array_index == 0)
|
||||||
present_value =
|
apdu_len =
|
||||||
Multistate_Output_Level[object_index][i];
|
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
|
||||||
len =
|
/* if no index was specified, then try to encode the entire list */
|
||||||
encode_application_unsigned(&apdu[apdu_len],
|
/* into one packet. */
|
||||||
present_value);
|
else if (array_index == BACNET_ARRAY_ALL) {
|
||||||
}
|
object_index =
|
||||||
/* add it if we have room */
|
Multistate_Output_Instance_To_Index(object_instance);
|
||||||
if ((apdu_len + len) < MAX_APDU)
|
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
|
||||||
apdu_len += len;
|
/* FIXME: check if we have room before adding it to APDU */
|
||||||
else {
|
if (Multistate_Output_Level[object_index][i] ==
|
||||||
*error_class = ERROR_CLASS_SERVICES;
|
MULTISTATE_NULL)
|
||||||
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
len = encode_application_null(&apdu[apdu_len]);
|
||||||
apdu_len = -1;
|
else {
|
||||||
break;
|
present_value =
|
||||||
}
|
Multistate_Output_Level[object_index][i];
|
||||||
}
|
len =
|
||||||
} else {
|
encode_application_unsigned(&apdu[apdu_len],
|
||||||
object_index =
|
present_value);
|
||||||
Multistate_Output_Instance_To_Index(object_instance);
|
}
|
||||||
if (array_index <= BACNET_MAX_PRIORITY) {
|
/* add it if we have room */
|
||||||
if (Multistate_Output_Level[object_index][array_index -
|
if ((apdu_len + len) < MAX_APDU)
|
||||||
1] == MULTISTATE_NULL)
|
apdu_len += len;
|
||||||
apdu_len = encode_application_null(&apdu[0]);
|
else {
|
||||||
else {
|
*error_class = ERROR_CLASS_SERVICES;
|
||||||
present_value =
|
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
||||||
Multistate_Output_Level[object_index][array_index -
|
apdu_len = -1;
|
||||||
1];
|
break;
|
||||||
apdu_len =
|
}
|
||||||
encode_application_unsigned(&apdu[0], present_value);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
object_index =
|
||||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
Multistate_Output_Instance_To_Index(object_instance);
|
||||||
apdu_len = -1;
|
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;
|
break;
|
||||||
case PROP_RELINQUISH_DEFAULT:
|
case PROP_RELINQUISH_DEFAULT:
|
||||||
present_value = MULTISTATE_RELINQUISH_DEFAULT;
|
present_value = MULTISTATE_RELINQUISH_DEFAULT;
|
||||||
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
||||||
break;
|
break;
|
||||||
case PROP_NUMBER_OF_STATES:
|
case PROP_NUMBER_OF_STATES:
|
||||||
apdu_len = encode_application_unsigned(&apdu[apdu_len],
|
apdu_len = encode_application_unsigned(&apdu[apdu_len],
|
||||||
MULTISTATE_NUMBER_OF_STATES);
|
MULTISTATE_NUMBER_OF_STATES);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*error_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
apdu_len = -1;
|
apdu_len = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns true if successful */
|
/* returns true if successful */
|
||||||
bool Multistate_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Multistate_Output_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code)
|
||||||
{
|
{
|
||||||
bool status = false; /* return value */
|
bool status = false; /* return value */
|
||||||
unsigned int object_index = 0;
|
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 < application_data_len: more data? */
|
||||||
/* FIXME: len == 0: unable to decode? */
|
/* FIXME: len == 0: unable to decode? */
|
||||||
switch (wp_data->object_property) {
|
switch (wp_data->object_property) {
|
||||||
case PROP_PRESENT_VALUE:
|
case PROP_PRESENT_VALUE:
|
||||||
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
|
||||||
priority = wp_data->priority;
|
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) {
|
|
||||||
/* Command priority 6 is reserved for use by Minimum On/Off
|
/* Command priority 6 is reserved for use by Minimum On/Off
|
||||||
algorithm and may not be used for other purposes in any
|
algorithm and may not be used for other purposes in any
|
||||||
object. */
|
object. */
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
|
||||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
(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 {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*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) {
|
break;
|
||||||
level = MULTISTATE_NULL;
|
case PROP_OUT_OF_SERVICE:
|
||||||
object_index =
|
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
|
||||||
Multistate_Output_Instance_To_Index(wp_data->
|
object_index =
|
||||||
object_instance);
|
Multistate_Output_Instance_To_Index(wp_data->
|
||||||
priority = wp_data->priority;
|
object_instance);
|
||||||
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
|
Multistate_Output_Out_Of_Service[object_index] =
|
||||||
priority--;
|
value.type.Boolean;
|
||||||
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;
|
status = true;
|
||||||
} else {
|
} else {
|
||||||
*error_class = ERROR_CLASS_PROPERTY;
|
*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_class = ERROR_CLASS_PROPERTY;
|
||||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||||
}
|
break;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -425,7 +437,8 @@ bool Multistate_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void testMultistateOutput(Test * pTest)
|
void testMultistateOutput(
|
||||||
|
Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
int len = 0;
|
int len = 0;
|
||||||
@@ -440,8 +453,7 @@ void testMultistateOutput(Test * pTest)
|
|||||||
|
|
||||||
len = Multistate_Output_Encode_Property_APDU(&apdu[0],
|
len = Multistate_Output_Encode_Property_APDU(&apdu[0],
|
||||||
instance,
|
instance,
|
||||||
PROP_OBJECT_IDENTIFIER,
|
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
|
||||||
BACNET_ARRAY_ALL, &error_class, &error_code);
|
|
||||||
ct_test(pTest, len != 0);
|
ct_test(pTest, len != 0);
|
||||||
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
|
||||||
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
|
||||||
@@ -454,7 +466,8 @@ void testMultistateOutput(Test * pTest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef TEST_MULTISTATE_OUTPUT
|
#ifdef TEST_MULTISTATE_OUTPUT
|
||||||
int main(void)
|
int main(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
Test *pTest;
|
Test *pTest;
|
||||||
bool rc;
|
bool rc;
|
||||||
@@ -471,5 +484,5 @@ int main(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* TEST_BINARY_INPUT */
|
#endif /* TEST_BINARY_INPUT */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "iam.h"
|
#include "iam.h"
|
||||||
@@ -61,9 +61,11 @@ static bool End_Of_File_Detected = false;
|
|||||||
static bool Error_Detected = false;
|
static bool Error_Detected = false;
|
||||||
static uint8_t Current_Invoke_ID = 0;
|
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,
|
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 */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
@@ -74,43 +76,47 @@ static void Atomic_Read_File_Error_Handler(BACNET_ADDRESS * src,
|
|||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAbortHandler(BACNET_ADDRESS * src,
|
void MyAbortHandler(
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t abort_reason,
|
||||||
|
bool server)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
(void) server;
|
(void) server;
|
||||||
printf("\r\nBACnet Abort!\r\n");
|
printf("\r\nBACnet Abort!\r\n");
|
||||||
printf("Abort Reason: %s\r\n",
|
printf("Abort Reason: %s\r\n", bactext_abort_reason_name(abort_reason));
|
||||||
bactext_abort_reason_name(abort_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyRejectHandler(BACNET_ADDRESS * src,
|
void MyRejectHandler(
|
||||||
uint8_t invoke_id, uint8_t reject_reason)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t reject_reason)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
printf("\r\nBACnet Reject!\r\n");
|
printf("\r\nBACnet Reject!\r\n");
|
||||||
printf("Reject Reason: %s\r\n",
|
printf("Reject Reason: %s\r\n", bactext_reject_reason_name(reject_reason));
|
||||||
bactext_reject_reason_name(reject_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AtomicReadFileAckHandler(uint8_t * service_request,
|
static void AtomicReadFileAckHandler(
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
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;
|
int len = 0;
|
||||||
BACNET_ATOMIC_READ_FILE_DATA data;
|
BACNET_ATOMIC_READ_FILE_DATA data;
|
||||||
FILE *pFile = NULL; /* stream pointer */
|
FILE *pFile = NULL; /* stream pointer */
|
||||||
size_t octets_written = 0;
|
size_t octets_written = 0;
|
||||||
|
|
||||||
(void) src; /* FIXME: validate the source address matches */
|
(void) src; /* FIXME: validate the source address matches */
|
||||||
len = arf_ack_decode_service_request(service_request,
|
len = arf_ack_decode_service_request(service_request, service_len, &data);
|
||||||
service_len, &data);
|
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
/* validate the parameters before storing data */
|
/* validate the parameters before storing data */
|
||||||
if ((data.access == FILE_STREAM_ACCESS) &&
|
if ((data.access == FILE_STREAM_ACCESS) &&
|
||||||
@@ -131,8 +137,7 @@ static void AtomicReadFileAckHandler(uint8_t * service_request,
|
|||||||
Local_File_Name);
|
Local_File_Name);
|
||||||
else
|
else
|
||||||
printf("\r%u bytes",
|
printf("\r%u bytes",
|
||||||
(data.type.stream.fileStartPosition +
|
(data.type.stream.fileStartPosition + octets_written));
|
||||||
octets_written));
|
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
}
|
}
|
||||||
if (data.endOfFile) {
|
if (data.endOfFile) {
|
||||||
@@ -143,8 +148,10 @@ static void AtomicReadFileAckHandler(uint8_t * service_request,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LocalIAmHandler(uint8_t * service_request,
|
static void LocalIAmHandler(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src)
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
uint32_t device_id = 0;
|
uint32_t device_id = 0;
|
||||||
@@ -164,15 +171,14 @@ static void LocalIAmHandler(uint8_t * service_request,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Init_Service_Handlers(void)
|
static void Init_Service_Handlers(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
/* we need to handle who-is
|
/* we need to handle who-is
|
||||||
to support dynamic device binding to us */
|
to support dynamic device binding to us */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||||
handler_who_is);
|
|
||||||
/* handle i-am to support binding to other devices */
|
/* handle i-am to support binding to other devices */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, LocalIAmHandler);
|
||||||
LocalIAmHandler);
|
|
||||||
/* set the handler for all the services we don't implement
|
/* set the handler for all the services we don't implement
|
||||||
It is required to send the proper reject message... */
|
It is required to send the proper reject message... */
|
||||||
apdu_set_unrecognized_service_handler_handler
|
apdu_set_unrecognized_service_handler_handler
|
||||||
@@ -190,7 +196,9 @@ static void Init_Service_Handlers(void)
|
|||||||
apdu_set_reject_handler(MyRejectHandler);
|
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 */
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
@@ -237,8 +245,7 @@ int main(int argc, char *argv[])
|
|||||||
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
||||||
Device_Number_Of_APDU_Retries();
|
Device_Number_Of_APDU_Retries();
|
||||||
/* try to bind with the device */
|
/* try to bind with the device */
|
||||||
Send_WhoIs(Target_Device_Object_Instance,
|
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
|
||||||
Target_Device_Object_Instance);
|
|
||||||
/* loop forever */
|
/* loop forever */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* increment timer - exit if timed out */
|
/* increment timer - exit if timed out */
|
||||||
@@ -253,8 +260,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
/* at least one second has passed */
|
/* at least one second has passed */
|
||||||
if (current_seconds != last_seconds)
|
if (current_seconds != last_seconds)
|
||||||
tsm_timer_milliseconds(((current_seconds -
|
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
|
||||||
last_seconds) * 1000));
|
|
||||||
if (End_Of_File_Detected || Error_Detected)
|
if (End_Of_File_Detected || Error_Detected)
|
||||||
break;
|
break;
|
||||||
/* wait until the device is bound, or timeout and quit */
|
/* wait until the device is bound, or timeout and quit */
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
|
|
||||||
#define PRINT_ENABLED 1
|
#define PRINT_ENABLED 1
|
||||||
|
|
||||||
@@ -66,51 +66,57 @@ static int32_t Target_Object_Index = BACNET_ARRAY_ALL;
|
|||||||
static BACNET_ADDRESS Target_Address;
|
static BACNET_ADDRESS Target_Address;
|
||||||
static bool Error_Detected = false;
|
static bool Error_Detected = false;
|
||||||
|
|
||||||
static void MyErrorHandler(BACNET_ADDRESS * src,
|
static void MyErrorHandler(
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
uint8_t invoke_id,
|
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 */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
printf("BACnet Error: %s: %s\r\n",
|
printf("BACnet Error: %s: %s\r\n",
|
||||||
bactext_error_class_name((int)error_class),
|
bactext_error_class_name((int) error_class),
|
||||||
bactext_error_code_name((int)error_code));
|
bactext_error_code_name((int) error_code));
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAbortHandler(BACNET_ADDRESS * src,
|
void MyAbortHandler(
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t abort_reason,
|
||||||
|
bool server)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
(void) server;
|
(void) server;
|
||||||
printf("BACnet Abort: %s\r\n",
|
printf("BACnet Abort: %s\r\n",
|
||||||
bactext_abort_reason_name((int)abort_reason));
|
bactext_abort_reason_name((int) abort_reason));
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyRejectHandler(BACNET_ADDRESS * src,
|
void MyRejectHandler(
|
||||||
uint8_t invoke_id, uint8_t reject_reason)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t reject_reason)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
printf("BACnet Reject: %s\r\n",
|
printf("BACnet Reject: %s\r\n",
|
||||||
bactext_reject_reason_name((int)reject_reason));
|
bactext_reject_reason_name((int) reject_reason));
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Init_Service_Handlers(void)
|
static void Init_Service_Handlers(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
/* we need to handle who-is
|
/* we need to handle who-is
|
||||||
to support dynamic device binding to us */
|
to support dynamic device binding to us */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||||
handler_who_is);
|
|
||||||
/* handle i-am to support binding to other devices */
|
/* handle i-am to support binding to other devices */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
|
||||||
handler_i_am_bind);
|
|
||||||
/* set the handler for all the services we don't implement
|
/* set the handler for all the services we don't implement
|
||||||
It is required to send the proper reject message... */
|
It is required to send the proper reject message... */
|
||||||
apdu_set_unrecognized_service_handler_handler
|
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,
|
apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||||
handler_read_property_ack);
|
handler_read_property_ack);
|
||||||
/* handle any errors coming back */
|
/* handle any errors coming back */
|
||||||
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler);
|
||||||
MyErrorHandler);
|
|
||||||
apdu_set_abort_handler(MyAbortHandler);
|
apdu_set_abort_handler(MyAbortHandler);
|
||||||
apdu_set_reject_handler(MyRejectHandler);
|
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 */
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
@@ -186,8 +193,7 @@ int main(int argc, char *argv[])
|
|||||||
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
||||||
Device_Number_Of_APDU_Retries();
|
Device_Number_Of_APDU_Retries();
|
||||||
/* try to bind with the device */
|
/* try to bind with the device */
|
||||||
Send_WhoIs(Target_Device_Object_Instance,
|
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
|
||||||
Target_Device_Object_Instance);
|
|
||||||
/* loop forever */
|
/* loop forever */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* increment timer - exit if timed out */
|
/* increment timer - exit if timed out */
|
||||||
@@ -202,8 +208,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
/* at least one second has passed */
|
/* at least one second has passed */
|
||||||
if (current_seconds != last_seconds)
|
if (current_seconds != last_seconds)
|
||||||
tsm_timer_milliseconds(((current_seconds -
|
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
|
||||||
last_seconds) * 1000));
|
|
||||||
if (Error_Detected)
|
if (Error_Detected)
|
||||||
break;
|
break;
|
||||||
/* wait until the device is bound, or timeout and quit */
|
/* wait until the device is bound, or timeout and quit */
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "iam.h"
|
#include "iam.h"
|
||||||
@@ -56,15 +56,16 @@ static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
|||||||
/* global variables used in this file */
|
/* global variables used in this file */
|
||||||
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
|
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
|
||||||
static BACNET_ADDRESS Target_Address;
|
static BACNET_ADDRESS Target_Address;
|
||||||
static BACNET_REINITIALIZED_STATE Reinitialize_State =
|
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_COLDSTART;
|
||||||
BACNET_REINIT_COLDSTART;
|
|
||||||
static char *Reinitialize_Password = NULL;
|
static char *Reinitialize_Password = NULL;
|
||||||
|
|
||||||
static bool Error_Detected = false;
|
static bool Error_Detected = false;
|
||||||
|
|
||||||
static void MyErrorHandler(BACNET_ADDRESS * src,
|
static void MyErrorHandler(
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
uint8_t invoke_id,
|
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 */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
@@ -75,30 +76,34 @@ static void MyErrorHandler(BACNET_ADDRESS * src,
|
|||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAbortHandler(BACNET_ADDRESS * src,
|
void MyAbortHandler(
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t abort_reason,
|
||||||
|
bool server)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
(void) server;
|
(void) server;
|
||||||
printf("BACnet Abort: %s\r\n",
|
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason));
|
||||||
bactext_abort_reason_name(abort_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyRejectHandler(BACNET_ADDRESS * src,
|
void MyRejectHandler(
|
||||||
uint8_t invoke_id, uint8_t reject_reason)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t reject_reason)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
printf("BACnet Reject: %s\r\n",
|
printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason));
|
||||||
bactext_reject_reason_name(reject_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyReinitializeDeviceSimpleAckHandler(BACNET_ADDRESS * src,
|
void MyReinitializeDeviceSimpleAckHandler(
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
uint8_t invoke_id)
|
uint8_t invoke_id)
|
||||||
{
|
{
|
||||||
(void) src;
|
(void) src;
|
||||||
@@ -106,15 +111,14 @@ void MyReinitializeDeviceSimpleAckHandler(BACNET_ADDRESS * src,
|
|||||||
printf("ReinitializeDevice Acknowledged!\r\n");
|
printf("ReinitializeDevice Acknowledged!\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Init_Service_Handlers(void)
|
static void Init_Service_Handlers(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
/* we need to handle who-is
|
/* we need to handle who-is
|
||||||
to support dynamic device binding to us */
|
to support dynamic device binding to us */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||||
handler_who_is);
|
|
||||||
/* handle i-am to support binding to other devices */
|
/* handle i-am to support binding to other devices */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
|
||||||
handler_i_am_bind);
|
|
||||||
/* set the handler for all the services we don't implement
|
/* set the handler for all the services we don't implement
|
||||||
It is required to send the proper reject message... */
|
It is required to send the proper reject message... */
|
||||||
apdu_set_unrecognized_service_handler_handler
|
apdu_set_unrecognized_service_handler_handler
|
||||||
@@ -133,7 +137,9 @@ static void Init_Service_Handlers(void)
|
|||||||
apdu_set_reject_handler(MyRejectHandler);
|
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 */
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
@@ -188,19 +194,14 @@ int main(int argc, char *argv[])
|
|||||||
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
||||||
Device_Number_Of_APDU_Retries();
|
Device_Number_Of_APDU_Retries();
|
||||||
/* try to bind with the device */
|
/* try to bind with the device */
|
||||||
Send_WhoIs(Target_Device_Object_Instance,
|
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
|
||||||
Target_Device_Object_Instance);
|
|
||||||
/* loop forever */
|
/* loop forever */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* increment timer - exit if timed out */
|
/* increment timer - exit if timed out */
|
||||||
current_seconds = time(NULL);
|
current_seconds = time(NULL);
|
||||||
|
|
||||||
/* returns 0 bytes on timeout */
|
/* returns 0 bytes on timeout */
|
||||||
pdu_len = datalink_receive(
|
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
|
||||||
&src,
|
|
||||||
&Rx_Buf[0],
|
|
||||||
MAX_MPDU,
|
|
||||||
timeout);
|
|
||||||
|
|
||||||
/* process */
|
/* process */
|
||||||
if (pdu_len) {
|
if (pdu_len) {
|
||||||
@@ -208,8 +209,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
/* at least one second has passed */
|
/* at least one second has passed */
|
||||||
if (current_seconds != last_seconds)
|
if (current_seconds != last_seconds)
|
||||||
tsm_timer_milliseconds(((current_seconds -
|
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
|
||||||
last_seconds) * 1000));
|
|
||||||
if (Error_Detected)
|
if (Error_Detected)
|
||||||
break;
|
break;
|
||||||
/* wait until the device is bound, or timeout and quit */
|
/* wait until the device is bound, or timeout and quit */
|
||||||
|
|||||||
@@ -55,13 +55,12 @@
|
|||||||
/* buffers used for receiving */
|
/* buffers used for receiving */
|
||||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
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 */
|
/* we need to handle who-is to support dynamic device binding */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||||
handler_who_is);
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS, handler_who_has);
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS,
|
|
||||||
handler_who_has);
|
|
||||||
/* set the handler for all the services we don't implement */
|
/* set the handler for all the services we don't implement */
|
||||||
/* It is required to send the proper reject message... */
|
/* It is required to send the proper reject message... */
|
||||||
apdu_set_unrecognized_service_handler_handler
|
apdu_set_unrecognized_service_handler_handler
|
||||||
@@ -83,8 +82,7 @@ static void Init_Service_Handlers(void)
|
|||||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
|
apdu_set_confirmed_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
|
||||||
handler_reinitialize_device);
|
handler_reinitialize_device);
|
||||||
apdu_set_unconfirmed_handler
|
apdu_set_unconfirmed_handler
|
||||||
(SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION,
|
(SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, handler_timesync_utc);
|
||||||
handler_timesync_utc);
|
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION,
|
||||||
handler_timesync);
|
handler_timesync);
|
||||||
/* handle communication so we can shutup when asked */
|
/* handle communication so we can shutup when asked */
|
||||||
@@ -93,12 +91,15 @@ static void Init_Service_Handlers(void)
|
|||||||
handler_device_communication_control);
|
handler_device_communication_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cleanup(void)
|
static void cleanup(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
datalink_cleanup();
|
datalink_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(
|
||||||
|
int argc,
|
||||||
|
char *argv[])
|
||||||
{
|
{
|
||||||
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
@@ -147,9 +148,7 @@ int main(int argc, char *argv[])
|
|||||||
"BACnet Stack Version %s\n"
|
"BACnet Stack Version %s\n"
|
||||||
"BACnet Device ID: %u\n"
|
"BACnet Device ID: %u\n"
|
||||||
"Max APDU: %d\n",
|
"Max APDU: %d\n",
|
||||||
BACnet_Version,
|
BACnet_Version, Device_Object_Instance_Number(), MAX_APDU);
|
||||||
Device_Object_Instance_Number(),
|
|
||||||
MAX_APDU);
|
|
||||||
Init_Service_Handlers();
|
Init_Service_Handlers();
|
||||||
BIP_Debug = true;
|
BIP_Debug = true;
|
||||||
if (!datalink_init(getenv("BACNET_IFACE")))
|
if (!datalink_init(getenv("BACNET_IFACE")))
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@@ -56,35 +56,38 @@ static int32_t Target_Object_Instance_Max = BACNET_MAX_INSTANCE;
|
|||||||
|
|
||||||
static bool Error_Detected = false;
|
static bool Error_Detected = false;
|
||||||
|
|
||||||
void MyAbortHandler(BACNET_ADDRESS * src,
|
void MyAbortHandler(
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t abort_reason,
|
||||||
|
bool server)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
(void) server;
|
(void) server;
|
||||||
printf("BACnet Abort: %s\r\n",
|
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason));
|
||||||
bactext_abort_reason_name(abort_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyRejectHandler(BACNET_ADDRESS * src,
|
void MyRejectHandler(
|
||||||
uint8_t invoke_id, uint8_t reject_reason)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t reject_reason)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
printf("BACnet Reject: %s\r\n",
|
printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason));
|
||||||
bactext_reject_reason_name(reject_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Init_Service_Handlers(void)
|
static void Init_Service_Handlers(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
/* we need to handle who-is
|
/* we need to handle who-is
|
||||||
to support dynamic device binding to us */
|
to support dynamic device binding to us */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||||
handler_who_is);
|
|
||||||
/* set the handler for all the services we don't implement
|
/* set the handler for all the services we don't implement
|
||||||
It is required to send the proper reject message... */
|
It is required to send the proper reject message... */
|
||||||
apdu_set_unrecognized_service_handler_handler
|
apdu_set_unrecognized_service_handler_handler
|
||||||
@@ -94,8 +97,7 @@ static void Init_Service_Handlers(void)
|
|||||||
handler_read_property);
|
handler_read_property);
|
||||||
/* handle the reply (request) coming in */
|
/* handle the reply (request) coming in */
|
||||||
apdu_set_unconfirmed_handler
|
apdu_set_unconfirmed_handler
|
||||||
(SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION,
|
(SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, handler_timesync_utc);
|
||||||
handler_timesync_utc);
|
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION,
|
||||||
handler_timesync);
|
handler_timesync);
|
||||||
/* handle any errors coming back */
|
/* handle any errors coming back */
|
||||||
@@ -103,7 +105,9 @@ static void Init_Service_Handlers(void)
|
|||||||
apdu_set_reject_handler(MyRejectHandler);
|
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 */
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "iam.h"
|
#include "iam.h"
|
||||||
@@ -49,15 +49,14 @@
|
|||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
|
||||||
static void Init_Service_Handlers(void)
|
static void Init_Service_Handlers(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
/* we need to handle who-is
|
/* we need to handle who-is
|
||||||
to support dynamic device binding to us */
|
to support dynamic device binding to us */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||||
handler_who_is);
|
|
||||||
/* handle i-am to support binding to other devices */
|
/* handle i-am to support binding to other devices */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
|
||||||
handler_i_am_bind);
|
|
||||||
/* set the handler for all the services we don't implement
|
/* set the handler for all the services we don't implement
|
||||||
It is required to send the proper reject message... */
|
It is required to send the proper reject message... */
|
||||||
apdu_set_unrecognized_service_handler_handler
|
apdu_set_unrecognized_service_handler_handler
|
||||||
@@ -67,7 +66,9 @@ static void Init_Service_Handlers(void)
|
|||||||
handler_read_property);
|
handler_read_property);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(
|
||||||
|
int argc,
|
||||||
|
char *argv[])
|
||||||
{
|
{
|
||||||
char *value_string = NULL;
|
char *value_string = NULL;
|
||||||
bool status = false;
|
bool status = false;
|
||||||
@@ -162,8 +163,7 @@ int main(int argc, char *argv[])
|
|||||||
cov_data.listOfValues.priority = BACNET_NO_PRIORITY;
|
cov_data.listOfValues.priority = BACNET_NO_PRIORITY;
|
||||||
/* optional index */
|
/* optional index */
|
||||||
if (argc > 10)
|
if (argc > 10)
|
||||||
cov_data.listOfValues.propertyArrayIndex =
|
cov_data.listOfValues.propertyArrayIndex = strtol(argv[10], NULL, 0);
|
||||||
strtol(argv[10], NULL, 0);
|
|
||||||
else
|
else
|
||||||
cov_data.listOfValues.propertyArrayIndex = BACNET_ARRAY_ALL;
|
cov_data.listOfValues.propertyArrayIndex = BACNET_ARRAY_ALL;
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "iam.h"
|
#include "iam.h"
|
||||||
@@ -59,35 +59,38 @@ static char *Target_Object_Name = NULL;
|
|||||||
|
|
||||||
static bool Error_Detected = false;
|
static bool Error_Detected = false;
|
||||||
|
|
||||||
void MyAbortHandler(BACNET_ADDRESS * src,
|
void MyAbortHandler(
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t abort_reason,
|
||||||
|
bool server)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
(void) server;
|
(void) server;
|
||||||
printf("BACnet Abort: %s\r\n",
|
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason));
|
||||||
bactext_abort_reason_name(abort_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyRejectHandler(BACNET_ADDRESS * src,
|
void MyRejectHandler(
|
||||||
uint8_t invoke_id, uint8_t reject_reason)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t reject_reason)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
printf("BACnet Reject: %s\r\n",
|
printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason));
|
||||||
bactext_reject_reason_name(reject_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Init_Service_Handlers(void)
|
static void Init_Service_Handlers(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
/* we need to handle who-is
|
/* we need to handle who-is
|
||||||
to support dynamic device binding to us */
|
to support dynamic device binding to us */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||||
handler_who_is);
|
|
||||||
/* set the handler for all the services we don't implement
|
/* set the handler for all the services we don't implement
|
||||||
It is required to send the proper reject message... */
|
It is required to send the proper reject message... */
|
||||||
apdu_set_unrecognized_service_handler_handler
|
apdu_set_unrecognized_service_handler_handler
|
||||||
@@ -96,14 +99,15 @@ static void Init_Service_Handlers(void)
|
|||||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||||
handler_read_property);
|
handler_read_property);
|
||||||
/* handle the reply (request) coming back */
|
/* handle the reply (request) coming back */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_HAVE,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_HAVE, handler_i_have);
|
||||||
handler_i_have);
|
|
||||||
/* handle any errors coming back */
|
/* handle any errors coming back */
|
||||||
apdu_set_abort_handler(MyAbortHandler);
|
apdu_set_abort_handler(MyAbortHandler);
|
||||||
apdu_set_reject_handler(MyRejectHandler);
|
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 */
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
@@ -157,8 +161,7 @@ int main(int argc, char *argv[])
|
|||||||
if (argc < 3)
|
if (argc < 3)
|
||||||
Send_WhoHas_Name(-1, -1, Target_Object_Name);
|
Send_WhoHas_Name(-1, -1, Target_Object_Name);
|
||||||
else
|
else
|
||||||
Send_WhoHas_Object(-1, -1,
|
Send_WhoHas_Object(-1, -1, Target_Object_Type, Target_Object_Instance);
|
||||||
Target_Object_Type, Target_Object_Instance);
|
|
||||||
/* loop forever */
|
/* loop forever */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* increment timer - exit if timed out */
|
/* increment timer - exit if timed out */
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "iam.h"
|
#include "iam.h"
|
||||||
@@ -55,35 +55,38 @@ static int32_t Target_Object_Instance_Max = BACNET_MAX_INSTANCE;
|
|||||||
|
|
||||||
static bool Error_Detected = false;
|
static bool Error_Detected = false;
|
||||||
|
|
||||||
void MyAbortHandler(BACNET_ADDRESS * src,
|
void MyAbortHandler(
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t abort_reason,
|
||||||
|
bool server)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
(void) server;
|
(void) server;
|
||||||
printf("BACnet Abort: %s\r\n",
|
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason));
|
||||||
bactext_abort_reason_name(abort_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyRejectHandler(BACNET_ADDRESS * src,
|
void MyRejectHandler(
|
||||||
uint8_t invoke_id, uint8_t reject_reason)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t reject_reason)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
printf("BACnet Reject: %s\r\n",
|
printf("BACnet Reject: %s\r\n", bactext_reject_reason_name(reject_reason));
|
||||||
bactext_reject_reason_name(reject_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Init_Service_Handlers(void)
|
static void Init_Service_Handlers(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
/* we need to handle who-is
|
/* we need to handle who-is
|
||||||
to support dynamic device binding to us */
|
to support dynamic device binding to us */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||||
handler_who_is);
|
|
||||||
/* set the handler for all the services we don't implement
|
/* set the handler for all the services we don't implement
|
||||||
It is required to send the proper reject message... */
|
It is required to send the proper reject message... */
|
||||||
apdu_set_unrecognized_service_handler_handler
|
apdu_set_unrecognized_service_handler_handler
|
||||||
@@ -92,14 +95,14 @@ static void Init_Service_Handlers(void)
|
|||||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||||
handler_read_property);
|
handler_read_property);
|
||||||
/* handle the reply (request) coming back */
|
/* handle the reply (request) coming back */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_add);
|
||||||
handler_i_am_add);
|
|
||||||
/* handle any errors coming back */
|
/* handle any errors coming back */
|
||||||
apdu_set_abort_handler(MyAbortHandler);
|
apdu_set_abort_handler(MyAbortHandler);
|
||||||
apdu_set_reject_handler(MyRejectHandler);
|
apdu_set_reject_handler(MyRejectHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print_address_cache(void)
|
static void print_address_cache(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
BACNET_ADDRESS address;
|
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 */
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "iam.h"
|
#include "iam.h"
|
||||||
@@ -61,9 +61,11 @@ static bool End_Of_File_Detected = false;
|
|||||||
static bool Error_Detected = false;
|
static bool Error_Detected = false;
|
||||||
static uint8_t Current_Invoke_ID = 0;
|
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,
|
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 */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
@@ -74,33 +76,38 @@ static void Atomic_Read_File_Error_Handler(BACNET_ADDRESS * src,
|
|||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAbortHandler(BACNET_ADDRESS * src,
|
void MyAbortHandler(
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t abort_reason,
|
||||||
|
bool server)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
(void) server;
|
(void) server;
|
||||||
printf("\r\nBACnet Abort!\r\n");
|
printf("\r\nBACnet Abort!\r\n");
|
||||||
printf("Abort Reason: %s\r\n",
|
printf("Abort Reason: %s\r\n", bactext_abort_reason_name(abort_reason));
|
||||||
bactext_abort_reason_name(abort_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyRejectHandler(BACNET_ADDRESS * src,
|
void MyRejectHandler(
|
||||||
uint8_t invoke_id, uint8_t reject_reason)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t reject_reason)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
printf("\r\nBACnet Reject!\r\n");
|
printf("\r\nBACnet Reject!\r\n");
|
||||||
printf("Reject Reason: %s\r\n",
|
printf("Reject Reason: %s\r\n", bactext_reject_reason_name(reject_reason));
|
||||||
bactext_reject_reason_name(reject_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LocalIAmHandler(uint8_t * service_request,
|
static void LocalIAmHandler(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src)
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
uint32_t device_id = 0;
|
uint32_t device_id = 0;
|
||||||
@@ -120,15 +127,14 @@ static void LocalIAmHandler(uint8_t * service_request,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Init_Service_Handlers(void)
|
static void Init_Service_Handlers(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
/* we need to handle who-is
|
/* we need to handle who-is
|
||||||
to support dynamic device binding to us */
|
to support dynamic device binding to us */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||||
handler_who_is);
|
|
||||||
/* handle i-am to support binding to other devices */
|
/* handle i-am to support binding to other devices */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, LocalIAmHandler);
|
||||||
LocalIAmHandler);
|
|
||||||
/* set the handler for all the services we don't implement
|
/* set the handler for all the services we don't implement
|
||||||
It is required to send the proper reject message... */
|
It is required to send the proper reject message... */
|
||||||
apdu_set_unrecognized_service_handler_handler
|
apdu_set_unrecognized_service_handler_handler
|
||||||
@@ -143,7 +149,9 @@ static void Init_Service_Handlers(void)
|
|||||||
apdu_set_reject_handler(MyRejectHandler);
|
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 */
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
@@ -193,8 +201,7 @@ int main(int argc, char *argv[])
|
|||||||
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
||||||
Device_Number_Of_APDU_Retries();
|
Device_Number_Of_APDU_Retries();
|
||||||
/* try to bind with the device */
|
/* try to bind with the device */
|
||||||
Send_WhoIs(Target_Device_Object_Instance,
|
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
|
||||||
Target_Device_Object_Instance);
|
|
||||||
/* loop forever */
|
/* loop forever */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* increment timer - exit if timed out */
|
/* increment timer - exit if timed out */
|
||||||
@@ -209,8 +216,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
/* at least one second has passed */
|
/* at least one second has passed */
|
||||||
if (current_seconds != last_seconds)
|
if (current_seconds != last_seconds)
|
||||||
tsm_timer_milliseconds(((current_seconds -
|
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
|
||||||
last_seconds) * 1000));
|
|
||||||
if (End_Of_File_Detected || Error_Detected) {
|
if (End_Of_File_Detected || Error_Detected) {
|
||||||
printf("\r\n");
|
printf("\r\n");
|
||||||
break;
|
break;
|
||||||
@@ -258,8 +264,7 @@ int main(int argc, char *argv[])
|
|||||||
invoke_id =
|
invoke_id =
|
||||||
Send_Atomic_Write_File_Stream
|
Send_Atomic_Write_File_Stream
|
||||||
(Target_Device_Object_Instance,
|
(Target_Device_Object_Instance,
|
||||||
Target_File_Object_Instance, fileStartPosition,
|
Target_File_Object_Instance, fileStartPosition, &fileData);
|
||||||
&fileData);
|
|
||||||
Current_Invoke_ID = invoke_id;
|
Current_Invoke_ID = invoke_id;
|
||||||
} else if (tsm_invoke_id_failed(invoke_id)) {
|
} else if (tsm_invoke_id_failed(invoke_id)) {
|
||||||
fprintf(stderr, "\rError: TSM Timeout!\r\n");
|
fprintf(stderr, "\rError: TSM Timeout!\r\n");
|
||||||
|
|||||||
@@ -28,10 +28,10 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ctype.h> /* toupper */
|
#include <ctype.h> /* toupper */
|
||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "iam.h"
|
#include "iam.h"
|
||||||
#include "arf.h"
|
#include "arf.h"
|
||||||
@@ -71,9 +71,11 @@ static uint8_t Target_Object_Property_Priority = 0;
|
|||||||
static BACNET_ADDRESS Target_Address;
|
static BACNET_ADDRESS Target_Address;
|
||||||
static bool Error_Detected = false;
|
static bool Error_Detected = false;
|
||||||
|
|
||||||
static void MyErrorHandler(BACNET_ADDRESS * src,
|
static void MyErrorHandler(
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
uint8_t invoke_id,
|
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 */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
@@ -84,32 +86,36 @@ static void MyErrorHandler(BACNET_ADDRESS * src,
|
|||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAbortHandler(BACNET_ADDRESS * src,
|
void MyAbortHandler(
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t abort_reason,
|
||||||
|
bool server)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
(void) server;
|
(void) server;
|
||||||
printf("\r\nBACnet Abort!\r\n");
|
printf("\r\nBACnet Abort!\r\n");
|
||||||
printf("Abort Reason: %s\r\n",
|
printf("Abort Reason: %s\r\n", bactext_abort_reason_name(abort_reason));
|
||||||
bactext_abort_reason_name(abort_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyRejectHandler(BACNET_ADDRESS * src,
|
void MyRejectHandler(
|
||||||
uint8_t invoke_id, uint8_t reject_reason)
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t reject_reason)
|
||||||
{
|
{
|
||||||
/* FIXME: verify src and invoke id */
|
/* FIXME: verify src and invoke id */
|
||||||
(void) src;
|
(void) src;
|
||||||
(void) invoke_id;
|
(void) invoke_id;
|
||||||
printf("\r\nBACnet Reject!\r\n");
|
printf("\r\nBACnet Reject!\r\n");
|
||||||
printf("Reject Reason: %s\r\n",
|
printf("Reject Reason: %s\r\n", bactext_reject_reason_name(reject_reason));
|
||||||
bactext_reject_reason_name(reject_reason));
|
|
||||||
Error_Detected = true;
|
Error_Detected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyWritePropertySimpleAckHandler(BACNET_ADDRESS * src,
|
void MyWritePropertySimpleAckHandler(
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
uint8_t invoke_id)
|
uint8_t invoke_id)
|
||||||
{
|
{
|
||||||
(void) src;
|
(void) src;
|
||||||
@@ -117,15 +123,14 @@ void MyWritePropertySimpleAckHandler(BACNET_ADDRESS * src,
|
|||||||
printf("\r\nWriteProperty Acknowledged!\r\n");
|
printf("\r\nWriteProperty Acknowledged!\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Init_Service_Handlers(void)
|
static void Init_Service_Handlers(
|
||||||
|
void)
|
||||||
{
|
{
|
||||||
/* we need to handle who-is
|
/* we need to handle who-is
|
||||||
to support dynamic device binding to us */
|
to support dynamic device binding to us */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||||
handler_who_is);
|
|
||||||
/* handle i-am to support binding to other devices */
|
/* handle i-am to support binding to other devices */
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
|
||||||
handler_i_am_bind);
|
|
||||||
/* set the handler for all the services we don't implement
|
/* set the handler for all the services we don't implement
|
||||||
It is required to send the proper reject message... */
|
It is required to send the proper reject message... */
|
||||||
apdu_set_unrecognized_service_handler_handler
|
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,
|
apdu_set_confirmed_simple_ack_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||||
MyWritePropertySimpleAckHandler);
|
MyWritePropertySimpleAckHandler);
|
||||||
/* handle any errors coming back */
|
/* handle any errors coming back */
|
||||||
apdu_set_error_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
|
apdu_set_error_handler(SERVICE_CONFIRMED_WRITE_PROPERTY, MyErrorHandler);
|
||||||
MyErrorHandler);
|
|
||||||
apdu_set_abort_handler(MyAbortHandler);
|
apdu_set_abort_handler(MyAbortHandler);
|
||||||
apdu_set_reject_handler(MyRejectHandler);
|
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 */
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
uint16_t pdu_len = 0;
|
uint16_t pdu_len = 0;
|
||||||
@@ -234,8 +240,7 @@ int main(int argc, char *argv[])
|
|||||||
"%s 123 1 0 85 4 100\r\n"
|
"%s 123 1 0 85 4 100\r\n"
|
||||||
"You could also send a relinquish command:\r\n"
|
"You could also send a relinquish command:\r\n"
|
||||||
"%s 123 1 0 85 0 0\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;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -317,8 +322,7 @@ int main(int argc, char *argv[])
|
|||||||
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
||||||
Device_Number_Of_APDU_Retries();
|
Device_Number_Of_APDU_Retries();
|
||||||
/* try to bind with the device */
|
/* try to bind with the device */
|
||||||
Send_WhoIs(Target_Device_Object_Instance,
|
Send_WhoIs(Target_Device_Object_Instance, Target_Device_Object_Instance);
|
||||||
Target_Device_Object_Instance);
|
|
||||||
/* loop forever */
|
/* loop forever */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* increment timer - exit if timed out */
|
/* increment timer - exit if timed out */
|
||||||
@@ -333,8 +337,7 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
/* at least one second has passed */
|
/* at least one second has passed */
|
||||||
if (current_seconds != last_seconds)
|
if (current_seconds != last_seconds)
|
||||||
tsm_timer_milliseconds(((current_seconds -
|
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
|
||||||
last_seconds) * 1000));
|
|
||||||
if (Error_Detected)
|
if (Error_Detected)
|
||||||
break;
|
break;
|
||||||
/* wait until the device is bound, or timeout and quit */
|
/* wait until the device is bound, or timeout and quit */
|
||||||
|
|||||||
@@ -39,24 +39,34 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
int abort_encode_apdu(uint8_t * apdu,
|
int abort_encode_apdu(
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server);
|
uint8_t * apdu,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t abort_reason,
|
||||||
|
bool server);
|
||||||
|
|
||||||
int abort_decode_service_request(uint8_t * apdu,
|
int abort_decode_service_request(
|
||||||
unsigned apdu_len, uint8_t * invoke_id, uint8_t * abort_reason);
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
uint8_t * invoke_id,
|
||||||
|
uint8_t * abort_reason);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
int abort_decode_apdu(uint8_t * apdu,
|
int abort_decode_apdu(
|
||||||
unsigned apdu_len, uint8_t * invoke_id, uint8_t * abort_reason,
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
uint8_t * invoke_id,
|
||||||
|
uint8_t * abort_reason,
|
||||||
bool * server);
|
bool * server);
|
||||||
|
|
||||||
void testAbort(Test * pTest);
|
void testAbort(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -41,35 +41,52 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void address_init(void);
|
void address_init(
|
||||||
|
void);
|
||||||
|
|
||||||
void address_add(uint32_t device_id,
|
void address_add(
|
||||||
unsigned max_apdu, BACNET_ADDRESS * src);
|
uint32_t device_id,
|
||||||
|
unsigned max_apdu,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
void address_remove_device(uint32_t device_id);
|
void address_remove_device(
|
||||||
|
uint32_t device_id);
|
||||||
|
|
||||||
bool address_get_by_device(uint32_t device_id,
|
bool address_get_by_device(
|
||||||
unsigned *max_apdu, BACNET_ADDRESS * src);
|
uint32_t device_id,
|
||||||
|
unsigned *max_apdu,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
bool address_get_by_index(unsigned index,
|
bool address_get_by_index(
|
||||||
uint32_t * device_id, unsigned *max_apdu, BACNET_ADDRESS * src);
|
unsigned index,
|
||||||
|
uint32_t * device_id,
|
||||||
bool address_get_device_id(BACNET_ADDRESS * src,
|
unsigned *max_apdu,
|
||||||
uint32_t *device_id);
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
unsigned address_count(void);
|
bool address_get_device_id(
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
|
uint32_t * device_id);
|
||||||
|
|
||||||
bool address_match(BACNET_ADDRESS * dest, BACNET_ADDRESS * src);
|
unsigned address_count(
|
||||||
|
void);
|
||||||
|
|
||||||
bool address_bind_request(uint32_t device_id,
|
bool address_match(
|
||||||
unsigned *max_apdu, BACNET_ADDRESS * src);
|
BACNET_ADDRESS * dest,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
void address_add_binding(uint32_t device_id,
|
bool address_bind_request(
|
||||||
unsigned max_apdu, BACNET_ADDRESS * src);
|
uint32_t device_id,
|
||||||
|
unsigned *max_apdu,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
|
void address_add_binding(
|
||||||
|
uint32_t device_id,
|
||||||
|
unsigned max_apdu,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -31,28 +31,35 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
void Analog_Input_Property_Lists(
|
void Analog_Input_Property_Lists(
|
||||||
const int **pRequired,
|
const int **pRequired,
|
||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary);
|
const int **pProprietary);
|
||||||
bool Analog_Input_Valid_Instance(uint32_t object_instance);
|
bool Analog_Input_Valid_Instance(
|
||||||
unsigned Analog_Input_Count(void);
|
uint32_t object_instance);
|
||||||
uint32_t Analog_Input_Index_To_Instance(unsigned index);
|
unsigned Analog_Input_Count(
|
||||||
char *Analog_Input_Name(uint32_t object_instance);
|
void);
|
||||||
|
uint32_t Analog_Input_Index_To_Instance(
|
||||||
|
unsigned index);
|
||||||
|
char *Analog_Input_Name(
|
||||||
|
uint32_t object_instance);
|
||||||
|
|
||||||
int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
|
int Analog_Input_Encode_Property_APDU(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
int32_t array_index,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testAnalogInput(Test * pTest);
|
void testAnalogInput(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+30
-17
@@ -33,40 +33,53 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void Analog_Output_Property_Lists(
|
void Analog_Output_Property_Lists(
|
||||||
const int **pRequired,
|
const int **pRequired,
|
||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary);
|
const int **pProprietary);
|
||||||
bool Analog_Output_Valid_Instance(uint32_t object_instance);
|
bool Analog_Output_Valid_Instance(
|
||||||
unsigned Analog_Output_Count(void);
|
uint32_t object_instance);
|
||||||
uint32_t Analog_Output_Index_To_Instance(unsigned index);
|
unsigned Analog_Output_Count(
|
||||||
char *Analog_Output_Name(uint32_t object_instance);
|
void);
|
||||||
float Analog_Output_Present_Value(uint32_t object_instance);
|
uint32_t Analog_Output_Index_To_Instance(
|
||||||
unsigned Analog_Output_Present_Value_Priority(uint32_t
|
unsigned index);
|
||||||
object_instance);
|
char *Analog_Output_Name(
|
||||||
bool Analog_Output_Present_Value_Set(uint32_t object_instance,
|
uint32_t object_instance);
|
||||||
float value, unsigned priority);
|
float Analog_Output_Present_Value(
|
||||||
bool Analog_Output_Present_Value_Relinquish(uint32_t object_instance,
|
uint32_t object_instance);
|
||||||
|
unsigned Analog_Output_Present_Value_Priority(
|
||||||
|
uint32_t object_instance);
|
||||||
|
bool Analog_Output_Present_Value_Set(
|
||||||
|
uint32_t object_instance,
|
||||||
|
float value,
|
||||||
|
unsigned priority);
|
||||||
|
bool Analog_Output_Present_Value_Relinquish(
|
||||||
|
uint32_t object_instance,
|
||||||
int priority);
|
int priority);
|
||||||
|
|
||||||
|
|
||||||
int Analog_Output_Encode_Property_APDU(uint8_t * apdu,
|
int Analog_Output_Encode_Property_APDU(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
int32_t array_index,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
bool Analog_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Analog_Output_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testAnalogOutput(Test * pTest);
|
void testAnalogOutput(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+61
-32
@@ -60,7 +60,7 @@ typedef struct _confirmed_service_ack_data {
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/* generic unconfirmed function handler */
|
/* generic unconfirmed function handler */
|
||||||
/* Suitable to handle the following services: */
|
/* Suitable to handle the following services: */
|
||||||
@@ -68,8 +68,11 @@ extern "C" {
|
|||||||
/* Unconfirmed_Event_Notification, Unconfirmed_Private_Transfer, */
|
/* Unconfirmed_Event_Notification, Unconfirmed_Private_Transfer, */
|
||||||
/* Unconfirmed_Text_Message, Time_Synchronization, Who_Has, */
|
/* Unconfirmed_Text_Message, Time_Synchronization, Who_Has, */
|
||||||
/* UTC_Time_Synchronization */
|
/* UTC_Time_Synchronization */
|
||||||
typedef void (*unconfirmed_function) (uint8_t * service_request,
|
typedef void (
|
||||||
uint16_t len, BACNET_ADDRESS * src);
|
*unconfirmed_function) (
|
||||||
|
uint8_t * service_request,
|
||||||
|
uint16_t len,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
/* generic confirmed function handler */
|
/* generic confirmed function handler */
|
||||||
/* Suitable to handle the following services: */
|
/* Suitable to handle the following services: */
|
||||||
@@ -87,72 +90,98 @@ extern "C" {
|
|||||||
/* Confirmed_Text_Message, Reinitialize_Device, */
|
/* Confirmed_Text_Message, Reinitialize_Device, */
|
||||||
/* VT_Open, VT_Close, VT_Data_Handler, */
|
/* VT_Open, VT_Close, VT_Data_Handler, */
|
||||||
/* Authenticate, Request_Key */
|
/* Authenticate, Request_Key */
|
||||||
typedef void (*confirmed_function) (uint8_t * service_request,
|
typedef void (
|
||||||
|
*confirmed_function) (
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
uint16_t service_len,
|
||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||||
|
|
||||||
/* generic confirmed simple ack function handler */
|
/* generic confirmed simple ack function handler */
|
||||||
typedef void (*confirmed_simple_ack_function) (BACNET_ADDRESS * src,
|
typedef void (
|
||||||
|
*confirmed_simple_ack_function) (
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
uint8_t invoke_id);
|
uint8_t invoke_id);
|
||||||
|
|
||||||
/* generic confirmed ack function handler */
|
/* generic confirmed ack function handler */
|
||||||
typedef void (*confirmed_ack_function) (uint8_t * service_request,
|
typedef void (
|
||||||
|
*confirmed_ack_function) (
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
uint16_t service_len,
|
||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
|
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
|
||||||
|
|
||||||
/* generic error reply function */
|
/* generic error reply function */
|
||||||
typedef void (*error_function) (BACNET_ADDRESS * src,
|
typedef void (
|
||||||
|
*error_function) (
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
uint8_t invoke_id,
|
uint8_t invoke_id,
|
||||||
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code);
|
BACNET_ERROR_CLASS error_class,
|
||||||
|
BACNET_ERROR_CODE error_code);
|
||||||
|
|
||||||
/* generic abort reply function */
|
/* generic abort reply function */
|
||||||
typedef void (*abort_function) (BACNET_ADDRESS * src,
|
typedef void (
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server);
|
*abort_function) (
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t abort_reason,
|
||||||
|
bool server);
|
||||||
|
|
||||||
/* generic reject reply function */
|
/* generic reject reply function */
|
||||||
typedef void (*reject_function) (BACNET_ADDRESS * src,
|
typedef void (
|
||||||
uint8_t invoke_id, uint8_t reject_reason);
|
*reject_function) (
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint8_t reject_reason);
|
||||||
|
|
||||||
void apdu_set_confirmed_ack_handler(BACNET_CONFIRMED_SERVICE
|
void apdu_set_confirmed_ack_handler(
|
||||||
service_choice, confirmed_ack_function pFunction);
|
BACNET_CONFIRMED_SERVICE service_choice,
|
||||||
|
confirmed_ack_function pFunction);
|
||||||
|
|
||||||
void apdu_set_confirmed_simple_ack_handler(BACNET_CONFIRMED_SERVICE
|
void apdu_set_confirmed_simple_ack_handler(
|
||||||
service_choice, confirmed_simple_ack_function pFunction);
|
BACNET_CONFIRMED_SERVICE service_choice,
|
||||||
|
confirmed_simple_ack_function pFunction);
|
||||||
|
|
||||||
/* configure reject for confirmed services that are not supported */
|
/* configure reject for confirmed services that are not supported */
|
||||||
void apdu_set_unrecognized_service_handler_handler(confirmed_function
|
void apdu_set_unrecognized_service_handler_handler(
|
||||||
pFunction);
|
confirmed_function pFunction);
|
||||||
|
|
||||||
void apdu_set_confirmed_handler(BACNET_CONFIRMED_SERVICE
|
void apdu_set_confirmed_handler(
|
||||||
service_choice, confirmed_function pFunction);
|
BACNET_CONFIRMED_SERVICE service_choice,
|
||||||
|
confirmed_function pFunction);
|
||||||
|
|
||||||
void apdu_set_unconfirmed_handler(BACNET_UNCONFIRMED_SERVICE
|
void apdu_set_unconfirmed_handler(
|
||||||
service_choice, unconfirmed_function pFunction);
|
BACNET_UNCONFIRMED_SERVICE service_choice,
|
||||||
|
unconfirmed_function pFunction);
|
||||||
|
|
||||||
/* returns true if the service is supported by a handler */
|
/* returns true if the service is supported by a handler */
|
||||||
bool apdu_service_supported(BACNET_SERVICES_SUPPORTED
|
bool apdu_service_supported(
|
||||||
service_supported);
|
BACNET_SERVICES_SUPPORTED service_supported);
|
||||||
|
|
||||||
void apdu_set_error_handler(BACNET_CONFIRMED_SERVICE service_choice,
|
void apdu_set_error_handler(
|
||||||
|
BACNET_CONFIRMED_SERVICE service_choice,
|
||||||
error_function pFunction);
|
error_function pFunction);
|
||||||
|
|
||||||
void apdu_set_abort_handler(abort_function pFunction);
|
void apdu_set_abort_handler(
|
||||||
|
abort_function pFunction);
|
||||||
|
|
||||||
void apdu_set_reject_handler(reject_function pFunction);
|
void apdu_set_reject_handler(
|
||||||
|
reject_function pFunction);
|
||||||
|
|
||||||
uint16_t apdu_decode_confirmed_service_request(uint8_t * apdu, /* APDU data */
|
uint16_t apdu_decode_confirmed_service_request(
|
||||||
|
uint8_t * apdu, /* APDU data */
|
||||||
uint16_t apdu_len,
|
uint16_t apdu_len,
|
||||||
BACNET_CONFIRMED_SERVICE_DATA * service_data,
|
BACNET_CONFIRMED_SERVICE_DATA * service_data,
|
||||||
uint8_t * service_choice,
|
uint8_t * service_choice,
|
||||||
uint8_t ** service_request, uint16_t * service_request_len);
|
uint8_t ** service_request,
|
||||||
|
uint16_t * service_request_len);
|
||||||
|
|
||||||
void apdu_handler(BACNET_ADDRESS * src, /* source address */
|
void apdu_handler(
|
||||||
uint8_t * apdu, /* APDU data */
|
BACNET_ADDRESS * src, /* source address */
|
||||||
|
uint8_t * apdu, /* APDU data */
|
||||||
uint16_t pdu_len); /* for confirmed messages */
|
uint16_t pdu_len); /* for confirmed messages */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -46,30 +46,37 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
bool arcnet_valid(void);
|
bool arcnet_valid(
|
||||||
void arcnet_cleanup(void);
|
void);
|
||||||
bool arcnet_init(char *interface_name);
|
void arcnet_cleanup(
|
||||||
|
void);
|
||||||
|
bool arcnet_init(
|
||||||
|
char *interface_name);
|
||||||
|
|
||||||
/* function to send a packet out the 802.2 socket */
|
/* function to send a packet out the 802.2 socket */
|
||||||
/* returns zero on success, non-zero on failure */
|
/* returns zero on success, non-zero on failure */
|
||||||
int arcnet_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
int arcnet_send_pdu(
|
||||||
|
BACNET_ADDRESS * dest, /* destination address */
|
||||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||||
uint8_t * pdu, /* any data to be sent - may be null */
|
uint8_t * pdu, /* any data to be sent - may be null */
|
||||||
unsigned pdu_len); /* number of bytes of data */
|
unsigned pdu_len); /* number of bytes of data */
|
||||||
|
|
||||||
/* receives an framed packet */
|
/* receives an framed packet */
|
||||||
/* returns the number of octets in the PDU, or zero on failure */
|
/* returns the number of octets in the PDU, or zero on failure */
|
||||||
uint16_t arcnet_receive(BACNET_ADDRESS * src, /* source address */
|
uint16_t arcnet_receive(
|
||||||
uint8_t * pdu, /* PDU data */
|
BACNET_ADDRESS * src, /* source address */
|
||||||
|
uint8_t * pdu, /* PDU data */
|
||||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||||
unsigned timeout); /* milliseconds to wait for a packet */
|
unsigned timeout); /* milliseconds to wait for a packet */
|
||||||
|
|
||||||
void arcnet_get_my_address(BACNET_ADDRESS * my_address);
|
void arcnet_get_my_address(
|
||||||
void arcnet_get_broadcast_address(BACNET_ADDRESS * dest); /* destination address */
|
BACNET_ADDRESS * my_address);
|
||||||
|
void arcnet_get_broadcast_address(
|
||||||
|
BACNET_ADDRESS * dest); /* destination address */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+32
-18
@@ -60,43 +60,57 @@ typedef struct BACnet_Atomic_Read_File_Data {
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/* Atomic Read File */
|
/* Atomic Read File */
|
||||||
/* encode service */
|
/* encode service */
|
||||||
int arf_encode_apdu(uint8_t * apdu,
|
int arf_encode_apdu(
|
||||||
uint8_t invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data);
|
uint8_t * apdu,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
BACNET_ATOMIC_READ_FILE_DATA * data);
|
||||||
|
|
||||||
/* decode the service request only */
|
/* decode the service request only */
|
||||||
int arf_decode_service_request(uint8_t * apdu,
|
int arf_decode_service_request(
|
||||||
unsigned apdu_len, BACNET_ATOMIC_READ_FILE_DATA * data);
|
uint8_t * apdu,
|
||||||
|
|
||||||
int arf_decode_apdu(uint8_t * apdu,
|
|
||||||
unsigned apdu_len,
|
unsigned apdu_len,
|
||||||
uint8_t * invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data);
|
BACNET_ATOMIC_READ_FILE_DATA * data);
|
||||||
|
|
||||||
|
int arf_decode_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
uint8_t * invoke_id,
|
||||||
|
BACNET_ATOMIC_READ_FILE_DATA * data);
|
||||||
|
|
||||||
/* Atomic Read File Ack */
|
/* Atomic Read File Ack */
|
||||||
|
|
||||||
/* encode service */
|
/* encode service */
|
||||||
int arf_ack_encode_apdu(uint8_t * apdu,
|
int arf_ack_encode_apdu(
|
||||||
uint8_t invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data);
|
uint8_t * apdu,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
BACNET_ATOMIC_READ_FILE_DATA * data);
|
||||||
|
|
||||||
/* decode the service request only */
|
/* decode the service request only */
|
||||||
int arf_ack_decode_service_request(uint8_t * apdu,
|
int arf_ack_decode_service_request(
|
||||||
unsigned apdu_len, BACNET_ATOMIC_READ_FILE_DATA * data);
|
uint8_t * apdu,
|
||||||
|
|
||||||
int arf_ack_decode_apdu(uint8_t * apdu,
|
|
||||||
unsigned apdu_len,
|
unsigned apdu_len,
|
||||||
uint8_t * invoke_id, BACNET_ATOMIC_READ_FILE_DATA * data);
|
BACNET_ATOMIC_READ_FILE_DATA * data);
|
||||||
|
|
||||||
|
int arf_ack_decode_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
uint8_t * invoke_id,
|
||||||
|
BACNET_ATOMIC_READ_FILE_DATA * data);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void test_AtomicReadFile(Test * pTest);
|
void test_AtomicReadFile(
|
||||||
void test_AtomicReadFileAck(Test * pTest);
|
Test * pTest);
|
||||||
|
void test_AtomicReadFileAck(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+20
-11
@@ -33,31 +33,40 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
void Analog_Value_Property_Lists(
|
void Analog_Value_Property_Lists(
|
||||||
const int **pRequired,
|
const int **pRequired,
|
||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary);
|
const int **pProprietary);
|
||||||
bool Analog_Value_Valid_Instance(uint32_t object_instance);
|
bool Analog_Value_Valid_Instance(
|
||||||
unsigned Analog_Value_Count(void);
|
uint32_t object_instance);
|
||||||
uint32_t Analog_Value_Index_To_Instance(unsigned index);
|
unsigned Analog_Value_Count(
|
||||||
char *Analog_Value_Name(uint32_t object_instance);
|
void);
|
||||||
|
uint32_t Analog_Value_Index_To_Instance(
|
||||||
|
unsigned index);
|
||||||
|
char *Analog_Value_Name(
|
||||||
|
uint32_t object_instance);
|
||||||
|
|
||||||
int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
|
int Analog_Value_Encode_Property_APDU(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
int32_t array_index,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Analog_Value_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testAnalog_Value(Test * pTest);
|
void testAnalog_Value(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+32
-18
@@ -56,42 +56,56 @@ typedef struct BACnet_Atomic_Write_File_Data {
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/* Atomic Write File */
|
/* Atomic Write File */
|
||||||
/* encode service */
|
/* encode service */
|
||||||
int awf_encode_apdu(uint8_t * apdu,
|
int awf_encode_apdu(
|
||||||
uint8_t invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
uint8_t * apdu,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
||||||
|
|
||||||
/* decode the service request only */
|
/* decode the service request only */
|
||||||
int awf_decode_service_request(uint8_t * apdu,
|
int awf_decode_service_request(
|
||||||
unsigned apdu_len, BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
uint8_t * apdu,
|
||||||
|
|
||||||
int awf_decode_apdu(uint8_t * apdu,
|
|
||||||
unsigned apdu_len,
|
unsigned apdu_len,
|
||||||
uint8_t * invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
||||||
|
|
||||||
|
int awf_decode_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
uint8_t * invoke_id,
|
||||||
|
BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
||||||
|
|
||||||
/* Atomic Write File Ack */
|
/* Atomic Write File Ack */
|
||||||
/* encode service */
|
/* encode service */
|
||||||
int awf_ack_encode_apdu(uint8_t * apdu,
|
int awf_ack_encode_apdu(
|
||||||
uint8_t invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
uint8_t * apdu,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
||||||
|
|
||||||
/* decode the service request only */
|
/* decode the service request only */
|
||||||
int awf_ack_decode_service_request(uint8_t * apdu,
|
int awf_ack_decode_service_request(
|
||||||
unsigned apdu_len, BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
uint8_t * apdu,
|
||||||
|
|
||||||
int awf_ack_decode_apdu(uint8_t * apdu,
|
|
||||||
unsigned apdu_len,
|
unsigned apdu_len,
|
||||||
uint8_t * invoke_id, BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
||||||
|
|
||||||
|
int awf_ack_decode_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
uint8_t * invoke_id,
|
||||||
|
BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void test_AtomicWriteFile(Test * pTest);
|
void test_AtomicWriteFile(
|
||||||
void test_AtomicWriteFileAck(Test * pTest);
|
Test * pTest);
|
||||||
|
void test_AtomicWriteFileAck(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -41,12 +41,16 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void bacnet_address_copy(BACNET_ADDRESS * dest, BACNET_ADDRESS * src);
|
void bacnet_address_copy(
|
||||||
bool bacnet_address_same(BACNET_ADDRESS * dest, BACNET_ADDRESS * src);
|
BACNET_ADDRESS * dest,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
bool bacnet_address_same(
|
||||||
|
BACNET_ADDRESS * dest,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ struct BACnet_Application_Data_Value;
|
|||||||
typedef struct BACnet_Application_Data_Value {
|
typedef struct BACnet_Application_Data_Value {
|
||||||
bool context_specific; /* true if context specific data */
|
bool context_specific; /* true if context specific data */
|
||||||
uint8_t context_tag; /* only used for context specific data */
|
uint8_t context_tag; /* only used for context specific data */
|
||||||
uint8_t tag; /* application tag data type */
|
uint8_t tag; /* application tag data type */
|
||||||
union {
|
union {
|
||||||
/* NULL - not needed as it is encoded in the tag alone */
|
/* NULL - not needed as it is encoded in the tag alone */
|
||||||
#if defined (BACAPP_BOOLEAN)
|
#if defined (BACAPP_BOOLEAN)
|
||||||
@@ -63,25 +63,25 @@ typedef struct BACnet_Application_Data_Value {
|
|||||||
#if defined (BACAPP_DOUBLE)
|
#if defined (BACAPP_DOUBLE)
|
||||||
double Double;
|
double Double;
|
||||||
#endif
|
#endif
|
||||||
#if defined (BACAPP_OCTET_STRING)
|
#if defined (BACAPP_OCTET_STRING)
|
||||||
BACNET_OCTET_STRING Octet_String;
|
BACNET_OCTET_STRING Octet_String;
|
||||||
#endif
|
#endif
|
||||||
#if defined (BACAPP_CHARACTER_STRING)
|
#if defined (BACAPP_CHARACTER_STRING)
|
||||||
BACNET_CHARACTER_STRING Character_String;
|
BACNET_CHARACTER_STRING Character_String;
|
||||||
#endif
|
#endif
|
||||||
#if defined (BACAPP_BIT_STRING)
|
#if defined (BACAPP_BIT_STRING)
|
||||||
BACNET_BIT_STRING Bit_String;
|
BACNET_BIT_STRING Bit_String;
|
||||||
#endif
|
#endif
|
||||||
#if defined (BACAPP_ENUMERATED)
|
#if defined (BACAPP_ENUMERATED)
|
||||||
int Enumerated;
|
int Enumerated;
|
||||||
#endif
|
#endif
|
||||||
#if defined (BACAPP_DATE)
|
#if defined (BACAPP_DATE)
|
||||||
BACNET_DATE Date;
|
BACNET_DATE Date;
|
||||||
#endif
|
#endif
|
||||||
#if defined (BACAPP_TIME)
|
#if defined (BACAPP_TIME)
|
||||||
BACNET_TIME Time;
|
BACNET_TIME Time;
|
||||||
#endif
|
#endif
|
||||||
#if defined (BACAPP_OBJECT_ID)
|
#if defined (BACAPP_OBJECT_ID)
|
||||||
BACNET_OBJECT_ID Object_Id;
|
BACNET_OBJECT_ID Object_Id;
|
||||||
#endif
|
#endif
|
||||||
} type;
|
} type;
|
||||||
@@ -91,38 +91,51 @@ typedef struct BACnet_Application_Data_Value {
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
int bacapp_encode_data(uint8_t * apdu,
|
int bacapp_encode_data(
|
||||||
|
uint8_t * apdu,
|
||||||
BACNET_APPLICATION_DATA_VALUE * value);
|
BACNET_APPLICATION_DATA_VALUE * value);
|
||||||
|
|
||||||
int bacapp_decode_application_data(uint8_t * apdu,
|
int bacapp_decode_application_data(
|
||||||
int max_apdu_len, BACNET_APPLICATION_DATA_VALUE * value);
|
uint8_t * apdu,
|
||||||
|
int max_apdu_len,
|
||||||
int bacapp_encode_application_data(uint8_t * apdu,
|
|
||||||
BACNET_APPLICATION_DATA_VALUE * value);
|
BACNET_APPLICATION_DATA_VALUE * value);
|
||||||
|
|
||||||
int bacapp_decode_context_data(uint8_t * apdu,
|
int bacapp_encode_application_data(
|
||||||
int max_apdu_len, BACNET_APPLICATION_DATA_VALUE * value,
|
uint8_t * apdu,
|
||||||
BACNET_PROPERTY_ID property);
|
BACNET_APPLICATION_DATA_VALUE * value);
|
||||||
|
|
||||||
int bacapp_encode_context_data(uint8_t * apdu,
|
int bacapp_decode_context_data(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int max_apdu_len,
|
||||||
BACNET_APPLICATION_DATA_VALUE * value,
|
BACNET_APPLICATION_DATA_VALUE * value,
|
||||||
BACNET_PROPERTY_ID property);
|
BACNET_PROPERTY_ID property);
|
||||||
|
|
||||||
int bacapp_encode_context_data_value(uint8_t * apdu,
|
int bacapp_encode_context_data(
|
||||||
uint8_t context_tag_number, BACNET_APPLICATION_DATA_VALUE * value);
|
uint8_t * apdu,
|
||||||
|
BACNET_APPLICATION_DATA_VALUE * value,
|
||||||
|
BACNET_PROPERTY_ID property);
|
||||||
|
|
||||||
BACNET_APPLICATION_TAG bacapp_context_tag_type(BACNET_PROPERTY_ID
|
int bacapp_encode_context_data_value(
|
||||||
property, uint8_t tag_number);
|
uint8_t * apdu,
|
||||||
|
uint8_t context_tag_number,
|
||||||
|
BACNET_APPLICATION_DATA_VALUE * value);
|
||||||
|
|
||||||
bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE * dest_value,
|
BACNET_APPLICATION_TAG bacapp_context_tag_type(
|
||||||
|
BACNET_PROPERTY_ID property,
|
||||||
|
uint8_t tag_number);
|
||||||
|
|
||||||
|
bool bacapp_copy(
|
||||||
|
BACNET_APPLICATION_DATA_VALUE * dest_value,
|
||||||
BACNET_APPLICATION_DATA_VALUE * src_value);
|
BACNET_APPLICATION_DATA_VALUE * src_value);
|
||||||
|
|
||||||
/* returns the length of data between an opening tag and a closing tag.
|
/* returns the length of data between an opening tag and a closing tag.
|
||||||
Expects that the first octet contain the opening tag.
|
Expects that the first octet contain the opening tag.
|
||||||
Include a value property identifier for context specific data
|
Include a value property identifier for context specific data
|
||||||
such as the value received in a WriteProperty request */
|
such as the value received in a WriteProperty request */
|
||||||
int bacapp_data_len(uint8_t * apdu, int max_apdu_len,
|
int bacapp_data_len(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int max_apdu_len,
|
||||||
BACNET_PROPERTY_ID property);
|
BACNET_PROPERTY_ID property);
|
||||||
|
|
||||||
#if PRINT_ENABLED
|
#if PRINT_ENABLED
|
||||||
@@ -134,9 +147,12 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BACAPP_PRINT_ENABLED
|
#ifdef BACAPP_PRINT_ENABLED
|
||||||
bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
|
bool bacapp_parse_application_data(
|
||||||
const char *argv, BACNET_APPLICATION_DATA_VALUE * value);
|
BACNET_APPLICATION_TAG tag_number,
|
||||||
bool bacapp_print_value(FILE * stream,
|
const char *argv,
|
||||||
|
BACNET_APPLICATION_DATA_VALUE * value);
|
||||||
|
bool bacapp_print_value(
|
||||||
|
FILE * stream,
|
||||||
BACNET_APPLICATION_DATA_VALUE * value,
|
BACNET_APPLICATION_DATA_VALUE * value,
|
||||||
BACNET_PROPERTY_ID property);
|
BACNET_PROPERTY_ID property);
|
||||||
#else
|
#else
|
||||||
@@ -147,14 +163,17 @@ extern "C" {
|
|||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
#include "datetime.h"
|
#include "datetime.h"
|
||||||
bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE * value,
|
bool bacapp_same_value(
|
||||||
|
BACNET_APPLICATION_DATA_VALUE * value,
|
||||||
BACNET_APPLICATION_DATA_VALUE * test_value);
|
BACNET_APPLICATION_DATA_VALUE * test_value);
|
||||||
|
|
||||||
void testBACnetApplicationDataLength(Test * pTest);
|
void testBACnetApplicationDataLength(
|
||||||
void testBACnetApplicationData(Test * pTest);
|
Test * pTest);
|
||||||
|
void testBACnetApplicationData(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+174
-64
@@ -45,133 +45,229 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/* from clause 20.2.1 General Rules for Encoding BACnet Tags */
|
/* from clause 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int encode_tag(uint8_t * apdu, uint8_t tag_number,
|
int encode_tag(
|
||||||
bool context_specific, uint32_t len_value_type);
|
uint8_t * apdu,
|
||||||
|
uint8_t tag_number,
|
||||||
|
bool context_specific,
|
||||||
|
uint32_t len_value_type);
|
||||||
|
|
||||||
/* from clause 20.2.1.3.2 Constructed Data */
|
/* from clause 20.2.1.3.2 Constructed Data */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int encode_opening_tag(uint8_t * apdu, uint8_t tag_number);
|
int encode_opening_tag(
|
||||||
int encode_closing_tag(uint8_t * apdu, uint8_t tag_number);
|
uint8_t * apdu,
|
||||||
int decode_tag_number(uint8_t * apdu, uint8_t * tag_number);
|
uint8_t tag_number);
|
||||||
int decode_tag_number_and_value(uint8_t * apdu, uint8_t * tag_number,
|
int encode_closing_tag(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint8_t tag_number);
|
||||||
|
int decode_tag_number(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint8_t * tag_number);
|
||||||
|
int decode_tag_number_and_value(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint8_t * tag_number,
|
||||||
uint32_t * value);
|
uint32_t * value);
|
||||||
/* returns true if the tag is context specific */
|
/* returns true if the tag is context specific */
|
||||||
bool decode_is_context_specific(uint8_t * apdu);
|
bool decode_is_context_specific(
|
||||||
|
uint8_t * apdu);
|
||||||
/* returns true if the tag is an opening tag and matches */
|
/* returns true if the tag is an opening tag and matches */
|
||||||
bool decode_is_opening_tag_number(uint8_t * apdu, uint8_t tag_number);
|
bool decode_is_opening_tag_number(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint8_t tag_number);
|
||||||
/* returns true if the tag is a closing tag and matches */
|
/* returns true if the tag is a closing tag and matches */
|
||||||
bool decode_is_closing_tag_number(uint8_t * apdu, uint8_t tag_number);
|
bool decode_is_closing_tag_number(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint8_t tag_number);
|
||||||
/* returns true if the tag is context specific and matches */
|
/* returns true if the tag is context specific and matches */
|
||||||
bool decode_is_context_tag(uint8_t * apdu, uint8_t tag_number);
|
bool decode_is_context_tag(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint8_t tag_number);
|
||||||
/* returns true if the tag is an opening tag */
|
/* returns true if the tag is an opening tag */
|
||||||
bool decode_is_opening_tag(uint8_t * apdu);
|
bool decode_is_opening_tag(
|
||||||
|
uint8_t * apdu);
|
||||||
/* returns true if the tag is a closing tag */
|
/* returns true if the tag is a closing tag */
|
||||||
bool decode_is_closing_tag(uint8_t * apdu);
|
bool decode_is_closing_tag(
|
||||||
|
uint8_t * apdu);
|
||||||
|
|
||||||
/* from clause 20.2.2 Encoding of a Null Value */
|
/* from clause 20.2.2 Encoding of a Null Value */
|
||||||
int encode_application_null(uint8_t * apdu);
|
int encode_application_null(
|
||||||
int encode_context_null(uint8_t * apdu, int tag_number);
|
uint8_t * apdu);
|
||||||
|
int encode_context_null(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int tag_number);
|
||||||
|
|
||||||
/* from clause 20.2.3 Encoding of a Boolean Value */
|
/* from clause 20.2.3 Encoding of a Boolean Value */
|
||||||
int encode_application_boolean(uint8_t * apdu, bool boolean_value);
|
int encode_application_boolean(
|
||||||
bool decode_boolean(uint32_t len_value);
|
uint8_t * apdu,
|
||||||
int encode_context_boolean(uint8_t * apdu, int tag_number,
|
|
||||||
bool boolean_value);
|
bool boolean_value);
|
||||||
bool decode_context_boolean(uint8_t * apdu);
|
bool decode_boolean(
|
||||||
|
uint32_t len_value);
|
||||||
|
int encode_context_boolean(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int tag_number,
|
||||||
|
bool boolean_value);
|
||||||
|
bool decode_context_boolean(
|
||||||
|
uint8_t * apdu);
|
||||||
|
|
||||||
/* from clause 20.2.10 Encoding of a Bit String Value */
|
/* from clause 20.2.10 Encoding of a Bit String Value */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int decode_bitstring(uint8_t * apdu, uint32_t len_value,
|
int decode_bitstring(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint32_t len_value,
|
||||||
BACNET_BIT_STRING * bit_string);
|
BACNET_BIT_STRING * bit_string);
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int encode_bitstring(uint8_t * apdu, BACNET_BIT_STRING * bit_string);
|
int encode_bitstring(
|
||||||
int encode_application_bitstring(uint8_t * apdu,
|
uint8_t * apdu,
|
||||||
BACNET_BIT_STRING * bit_string);
|
BACNET_BIT_STRING * bit_string);
|
||||||
int encode_context_bitstring(uint8_t * apdu, int tag_number,
|
int encode_application_bitstring(
|
||||||
|
uint8_t * apdu,
|
||||||
|
BACNET_BIT_STRING * bit_string);
|
||||||
|
int encode_context_bitstring(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int tag_number,
|
||||||
BACNET_BIT_STRING * bit_string);
|
BACNET_BIT_STRING * bit_string);
|
||||||
|
|
||||||
/* from clause 20.2.6 Encoding of a Real Number Value */
|
/* from clause 20.2.6 Encoding of a Real Number Value */
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int encode_application_real(uint8_t * apdu, float value);
|
int encode_application_real(
|
||||||
int encode_context_real(uint8_t * apdu, int tag_number, float value);
|
uint8_t * apdu,
|
||||||
|
float value);
|
||||||
|
int encode_context_real(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int tag_number,
|
||||||
|
float value);
|
||||||
|
|
||||||
/* from clause 20.2.14 Encoding of an Object Identifier Value */
|
/* from clause 20.2.14 Encoding of an Object Identifier Value */
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int decode_object_id(uint8_t * apdu, int *object_type,
|
int decode_object_id(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int *object_type,
|
||||||
uint32_t * instance);
|
uint32_t * instance);
|
||||||
int encode_bacnet_object_id(uint8_t * apdu, int object_type,
|
int encode_bacnet_object_id(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int object_type,
|
||||||
uint32_t instance);
|
uint32_t instance);
|
||||||
int encode_context_object_id(uint8_t * apdu, int tag_number,
|
int encode_context_object_id(
|
||||||
int object_type, uint32_t instance);
|
uint8_t * apdu,
|
||||||
int encode_application_object_id(uint8_t * apdu, int object_type,
|
int tag_number,
|
||||||
|
int object_type,
|
||||||
|
uint32_t instance);
|
||||||
|
int encode_application_object_id(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int object_type,
|
||||||
uint32_t instance);
|
uint32_t instance);
|
||||||
|
|
||||||
/* from clause 20.2.8 Encoding of an Octet String Value */
|
/* from clause 20.2.8 Encoding of an Octet String Value */
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int encode_octet_string(uint8_t * apdu,
|
int encode_octet_string(
|
||||||
|
uint8_t * apdu,
|
||||||
BACNET_OCTET_STRING * octet_string);
|
BACNET_OCTET_STRING * octet_string);
|
||||||
int encode_application_octet_string(uint8_t * apdu,
|
int encode_application_octet_string(
|
||||||
|
uint8_t * apdu,
|
||||||
BACNET_OCTET_STRING * octet_string);
|
BACNET_OCTET_STRING * octet_string);
|
||||||
int encode_context_octet_string(uint8_t * apdu,
|
int encode_context_octet_string(
|
||||||
int tag_number, BACNET_OCTET_STRING * octet_string);
|
uint8_t * apdu,
|
||||||
int decode_octet_string(uint8_t * apdu, uint32_t len_value,
|
int tag_number,
|
||||||
|
BACNET_OCTET_STRING * octet_string);
|
||||||
|
int decode_octet_string(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint32_t len_value,
|
||||||
BACNET_OCTET_STRING * octet_string);
|
BACNET_OCTET_STRING * octet_string);
|
||||||
|
|
||||||
|
|
||||||
/* from clause 20.2.9 Encoding of a Character String Value */
|
/* from clause 20.2.9 Encoding of a Character String Value */
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int encode_bacnet_character_string(uint8_t * apdu,
|
int encode_bacnet_character_string(
|
||||||
|
uint8_t * apdu,
|
||||||
BACNET_CHARACTER_STRING * char_string);
|
BACNET_CHARACTER_STRING * char_string);
|
||||||
int encode_application_character_string(uint8_t * apdu,
|
int encode_application_character_string(
|
||||||
|
uint8_t * apdu,
|
||||||
BACNET_CHARACTER_STRING * char_string);
|
BACNET_CHARACTER_STRING * char_string);
|
||||||
int encode_context_character_string(uint8_t * apdu, int tag_number,
|
int encode_context_character_string(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int tag_number,
|
||||||
BACNET_CHARACTER_STRING * char_string);
|
BACNET_CHARACTER_STRING * char_string);
|
||||||
int decode_character_string(uint8_t * apdu, uint32_t len_value,
|
int decode_character_string(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint32_t len_value,
|
||||||
BACNET_CHARACTER_STRING * char_string);
|
BACNET_CHARACTER_STRING * char_string);
|
||||||
|
|
||||||
/* from clause 20.2.4 Encoding of an Unsigned Integer Value */
|
/* from clause 20.2.4 Encoding of an Unsigned Integer Value */
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int encode_bacnet_unsigned(uint8_t * apdu, uint32_t value);
|
int encode_bacnet_unsigned(
|
||||||
int encode_context_unsigned(uint8_t * apdu, int tag_number,
|
uint8_t * apdu,
|
||||||
uint32_t value);
|
uint32_t value);
|
||||||
int encode_application_unsigned(uint8_t * apdu, uint32_t value);
|
int encode_context_unsigned(
|
||||||
int decode_unsigned(uint8_t * apdu, uint32_t len_value,
|
uint8_t * apdu,
|
||||||
|
int tag_number,
|
||||||
|
uint32_t value);
|
||||||
|
int encode_application_unsigned(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint32_t value);
|
||||||
|
int decode_unsigned(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint32_t len_value,
|
||||||
uint32_t * value);
|
uint32_t * value);
|
||||||
|
|
||||||
/* from clause 20.2.5 Encoding of a Signed Integer Value */
|
/* from clause 20.2.5 Encoding of a Signed Integer Value */
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int encode_bacnet_signed(uint8_t * apdu, int32_t value);
|
int encode_bacnet_signed(
|
||||||
int encode_application_signed(uint8_t * apdu, int32_t value);
|
uint8_t * apdu,
|
||||||
int encode_context_signed(uint8_t * apdu, int tag_number,
|
|
||||||
int32_t value);
|
int32_t value);
|
||||||
int decode_signed(uint8_t * apdu, uint32_t len_value, int32_t * value);
|
int encode_application_signed(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int32_t value);
|
||||||
|
int encode_context_signed(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int tag_number,
|
||||||
|
int32_t value);
|
||||||
|
int decode_signed(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint32_t len_value,
|
||||||
|
int32_t * value);
|
||||||
|
|
||||||
/* from clause 20.2.11 Encoding of an Enumerated Value */
|
/* from clause 20.2.11 Encoding of an Enumerated Value */
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int decode_enumerated(uint8_t * apdu, uint32_t len_value, int *value);
|
int decode_enumerated(
|
||||||
int encode_bacnet_enumerated(uint8_t * apdu, int value);
|
uint8_t * apdu,
|
||||||
int encode_application_enumerated(uint8_t * apdu, int value);
|
uint32_t len_value,
|
||||||
int encode_context_enumerated(uint8_t * apdu, int tag_number,
|
int *value);
|
||||||
|
int encode_bacnet_enumerated(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int value);
|
||||||
|
int encode_application_enumerated(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int value);
|
||||||
|
int encode_context_enumerated(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int tag_number,
|
||||||
int value);
|
int value);
|
||||||
|
|
||||||
/* from clause 20.2.13 Encoding of a Time Value */
|
/* from clause 20.2.13 Encoding of a Time Value */
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int encode_bacnet_time(uint8_t * apdu, BACNET_TIME * btime);
|
int encode_bacnet_time(
|
||||||
int encode_application_time(uint8_t * apdu, BACNET_TIME * btime);
|
uint8_t * apdu,
|
||||||
int decode_bacnet_time(uint8_t * apdu, BACNET_TIME * btime);
|
BACNET_TIME * btime);
|
||||||
int encode_context_time(uint8_t * apdu, int tag_number,
|
int encode_application_time(
|
||||||
|
uint8_t * apdu,
|
||||||
|
BACNET_TIME * btime);
|
||||||
|
int decode_bacnet_time(
|
||||||
|
uint8_t * apdu,
|
||||||
|
BACNET_TIME * btime);
|
||||||
|
int encode_context_time(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int tag_number,
|
||||||
BACNET_TIME * btime);
|
BACNET_TIME * btime);
|
||||||
|
|
||||||
/* BACnet Date */
|
/* BACnet Date */
|
||||||
@@ -183,24 +279,38 @@ extern "C" {
|
|||||||
/* from clause 20.2.12 Encoding of a Date Value */
|
/* from clause 20.2.12 Encoding of a Date Value */
|
||||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int encode_bacnet_date(uint8_t * apdu, BACNET_DATE * bdate);
|
int encode_bacnet_date(
|
||||||
int encode_application_date(uint8_t * apdu, BACNET_DATE * bdate);
|
uint8_t * apdu,
|
||||||
int encode_context_date(uint8_t * apdu, int tag_number,
|
BACNET_DATE * bdate);
|
||||||
|
int encode_application_date(
|
||||||
|
uint8_t * apdu,
|
||||||
|
BACNET_DATE * bdate);
|
||||||
|
int encode_context_date(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int tag_number,
|
||||||
|
BACNET_DATE * bdate);
|
||||||
|
int decode_date(
|
||||||
|
uint8_t * apdu,
|
||||||
BACNET_DATE * bdate);
|
BACNET_DATE * bdate);
|
||||||
int decode_date(uint8_t * apdu, BACNET_DATE * bdate);
|
|
||||||
|
|
||||||
/* from clause 20.1.2.4 max-segments-accepted */
|
/* from clause 20.1.2.4 max-segments-accepted */
|
||||||
/* and clause 20.1.2.5 max-APDU-length-accepted */
|
/* and clause 20.1.2.5 max-APDU-length-accepted */
|
||||||
/* returns the encoded octet */
|
/* returns the encoded octet */
|
||||||
uint8_t encode_max_segs_max_apdu(int max_segs, int max_apdu);
|
uint8_t encode_max_segs_max_apdu(
|
||||||
int decode_max_segs(uint8_t octet);
|
int max_segs,
|
||||||
int decode_max_apdu(uint8_t octet);
|
int max_apdu);
|
||||||
|
int decode_max_segs(
|
||||||
|
uint8_t octet);
|
||||||
|
int decode_max_apdu(
|
||||||
|
uint8_t octet);
|
||||||
|
|
||||||
/* returns the number of apdu bytes consumed */
|
/* returns the number of apdu bytes consumed */
|
||||||
int encode_simple_ack(uint8_t * apdu, uint8_t invoke_id,
|
int encode_simple_ack(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint8_t invoke_id,
|
||||||
uint8_t service_choice);
|
uint8_t service_choice);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -71,10 +71,10 @@ struct BACnet_Device_Address {
|
|||||||
/* DNET,DLEN,DADR or SNET,SLEN,SADR */
|
/* DNET,DLEN,DADR or SNET,SLEN,SADR */
|
||||||
/* the following are used if the device is behind a router */
|
/* the following are used if the device is behind a router */
|
||||||
/* net = 0 indicates local */
|
/* net = 0 indicates local */
|
||||||
uint16_t net; /* BACnet network number */
|
uint16_t net; /* BACnet network number */
|
||||||
/* LEN = 0 denotes broadcast MAC ADR and ADR field is absent */
|
/* LEN = 0 denotes broadcast MAC ADR and ADR field is absent */
|
||||||
/* LEN > 0 specifies length of ADR field */
|
/* LEN > 0 specifies length of ADR field */
|
||||||
uint8_t len; /* length of MAC address */
|
uint8_t len; /* length of MAC address */
|
||||||
uint8_t adr[MAX_MAC_LEN]; /* hwaddr (MAC) address */
|
uint8_t adr[MAX_MAC_LEN]; /* hwaddr (MAC) address */
|
||||||
};
|
};
|
||||||
typedef struct BACnet_Device_Address BACNET_ADDRESS;
|
typedef struct BACnet_Device_Address BACNET_ADDRESS;
|
||||||
|
|||||||
@@ -279,12 +279,12 @@ typedef enum {
|
|||||||
PROP_RAMP_RATE = 241,
|
PROP_RAMP_RATE = 241,
|
||||||
PROP_STEP_INCREMENT = 242,
|
PROP_STEP_INCREMENT = 242,
|
||||||
PROP_SYSTEM_FAILURE_VALUE = 243
|
PROP_SYSTEM_FAILURE_VALUE = 243
|
||||||
/* The special property identifiers all, optional, and required */
|
/* The special property identifiers all, optional, and required */
|
||||||
/* are reserved for use in the ReadPropertyConditional and */
|
/* are reserved for use in the ReadPropertyConditional and */
|
||||||
/* ReadPropertyMultiple services or services not defined in this standard. */
|
/* ReadPropertyMultiple services or services not defined in this standard. */
|
||||||
/* Enumerated values 0-511 are reserved for definition by ASHRAE. */
|
/* Enumerated values 0-511 are reserved for definition by ASHRAE. */
|
||||||
/* Enumerated values 512-4194303 may be used by others subject to the */
|
/* Enumerated values 512-4194303 may be used by others subject to the */
|
||||||
/* procedures and constraints described in Clause 23. */
|
/* procedures and constraints described in Clause 23. */
|
||||||
} BACNET_PROPERTY_ID;
|
} BACNET_PROPERTY_ID;
|
||||||
#define MAX_BACNET_PROPERTY_ID 4194303
|
#define MAX_BACNET_PROPERTY_ID 4194303
|
||||||
|
|
||||||
@@ -294,11 +294,11 @@ typedef enum {
|
|||||||
} BACNET_ACTION;
|
} BACNET_ACTION;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MIN_BINARY_PV = 0, /* for validating incoming values */
|
MIN_BINARY_PV = 0, /* for validating incoming values */
|
||||||
BINARY_INACTIVE = 0,
|
BINARY_INACTIVE = 0,
|
||||||
BINARY_ACTIVE = 1,
|
BINARY_ACTIVE = 1,
|
||||||
MAX_BINARY_PV = 1, /* for validating incoming values */
|
MAX_BINARY_PV = 1, /* for validating incoming values */
|
||||||
BINARY_NULL = 2 /* our homemade way of storing this info */
|
BINARY_NULL = 2 /* our homemade way of storing this info */
|
||||||
} BACNET_BINARY_PV;
|
} BACNET_BINARY_PV;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -538,10 +538,10 @@ typedef enum {
|
|||||||
UNITS_SQUARE_METERS_PER_NEWTON = 185,
|
UNITS_SQUARE_METERS_PER_NEWTON = 185,
|
||||||
UNITS_WATTS_PER_METER_PER_DEGREE_KELVIN = 189,
|
UNITS_WATTS_PER_METER_PER_DEGREE_KELVIN = 189,
|
||||||
UNITS_WATTS_PER_SQUARE_METER_DEGREE_KELVIN = 141
|
UNITS_WATTS_PER_SQUARE_METER_DEGREE_KELVIN = 141
|
||||||
/* Enumerated values 0-255 are reserved for definition by ASHRAE. */
|
/* Enumerated values 0-255 are reserved for definition by ASHRAE. */
|
||||||
/* Enumerated values 256-65535 may be used by others subject to */
|
/* Enumerated values 256-65535 may be used by others subject to */
|
||||||
/* the procedures and constraints described in Clause 23. */
|
/* the procedures and constraints described in Clause 23. */
|
||||||
/* The last enumeration used in this version is 189. */
|
/* The last enumeration used in this version is 189. */
|
||||||
} BACNET_ENGINEERING_UNITS;
|
} BACNET_ENGINEERING_UNITS;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -573,9 +573,9 @@ typedef enum {
|
|||||||
PROGRAM_ERROR_INTERNAL = 2,
|
PROGRAM_ERROR_INTERNAL = 2,
|
||||||
PROGRAM_ERROR_PROGRAM = 3,
|
PROGRAM_ERROR_PROGRAM = 3,
|
||||||
PROGRAM_ERROR_OTHER = 4
|
PROGRAM_ERROR_OTHER = 4
|
||||||
/* Enumerated values 0-63 are reserved for definition by ASHRAE. */
|
/* Enumerated values 0-63 are reserved for definition by ASHRAE. */
|
||||||
/* Enumerated values 64-65535 may be used by others subject to */
|
/* Enumerated values 64-65535 may be used by others subject to */
|
||||||
/* the procedures and constraints described in Clause 23. */
|
/* the procedures and constraints described in Clause 23. */
|
||||||
} BACNET_PROGRAM_ERROR;
|
} BACNET_PROGRAM_ERROR;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -592,9 +592,9 @@ typedef enum {
|
|||||||
RELIABILITY_CONFIGURATION_ERROR = 10,
|
RELIABILITY_CONFIGURATION_ERROR = 10,
|
||||||
RELIABILITY_COMMUNICATION_FAILURE = 12,
|
RELIABILITY_COMMUNICATION_FAILURE = 12,
|
||||||
RELIABILITY_TRIPPED = 13
|
RELIABILITY_TRIPPED = 13
|
||||||
/* Enumerated values 0-63 are reserved for definition by ASHRAE. */
|
/* Enumerated values 0-63 are reserved for definition by ASHRAE. */
|
||||||
/* Enumerated values 64-65535 may be used by others subject to */
|
/* Enumerated values 64-65535 may be used by others subject to */
|
||||||
/* the procedures and constraints described in Clause 23. */
|
/* the procedures and constraints described in Clause 23. */
|
||||||
} BACNET_RELIABILITY;
|
} BACNET_RELIABILITY;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -610,13 +610,13 @@ typedef enum {
|
|||||||
EVENT_EXTENDED = 9,
|
EVENT_EXTENDED = 9,
|
||||||
EVENT_BUFFER_READY = 10,
|
EVENT_BUFFER_READY = 10,
|
||||||
EVENT_UNSIGNED_RANGE = 11
|
EVENT_UNSIGNED_RANGE = 11
|
||||||
/* Enumerated values 0-63 are reserved for definition by ASHRAE. */
|
/* Enumerated values 0-63 are reserved for definition by ASHRAE. */
|
||||||
/* Enumerated values 64-65535 may be used by others subject to */
|
/* Enumerated values 64-65535 may be used by others subject to */
|
||||||
/* the procedures and constraints described in Clause 23. */
|
/* the procedures and constraints described in Clause 23. */
|
||||||
/* It is expected that these enumerated values will correspond to */
|
/* It is expected that these enumerated values will correspond to */
|
||||||
/* the use of the complex-event-type CHOICE [6] of the */
|
/* the use of the complex-event-type CHOICE [6] of the */
|
||||||
/* BACnetNotificationParameters production. */
|
/* BACnetNotificationParameters production. */
|
||||||
/* The last enumeration used in this version is 11. */
|
/* The last enumeration used in this version is 11. */
|
||||||
} BACNET_EVENT_TYPE;
|
} BACNET_EVENT_TYPE;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -643,9 +643,9 @@ typedef enum {
|
|||||||
LIFE_SAFETY_MODE_AUTOMATIC_RELEASE_DISABLED = 13,
|
LIFE_SAFETY_MODE_AUTOMATIC_RELEASE_DISABLED = 13,
|
||||||
LIFE_SAFETY_MODE_DEFAULT = 14,
|
LIFE_SAFETY_MODE_DEFAULT = 14,
|
||||||
MAX_LIFE_SAFETY_MODE = 14
|
MAX_LIFE_SAFETY_MODE = 14
|
||||||
/* Enumerated values 0-255 are reserved for definition by ASHRAE. */
|
/* Enumerated values 0-255 are reserved for definition by ASHRAE. */
|
||||||
/* Enumerated values 256-65535 may be used by others subject to */
|
/* Enumerated values 256-65535 may be used by others subject to */
|
||||||
/* procedures and constraints described in Clause 23. */
|
/* procedures and constraints described in Clause 23. */
|
||||||
} BACNET_LIFE_SAFETY_MODE;
|
} BACNET_LIFE_SAFETY_MODE;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -691,9 +691,9 @@ typedef enum {
|
|||||||
LIFE_SAFETY_STATE_SUPERVISORY = 22,
|
LIFE_SAFETY_STATE_SUPERVISORY = 22,
|
||||||
LIFE_SAFETY_STATE_TEST_SUPERVISORY = 23,
|
LIFE_SAFETY_STATE_TEST_SUPERVISORY = 23,
|
||||||
MAX_LIFE_SAFETY_STATE = 0
|
MAX_LIFE_SAFETY_STATE = 0
|
||||||
/* Enumerated values 0-255 are reserved for definition by ASHRAE. */
|
/* Enumerated values 0-255 are reserved for definition by ASHRAE. */
|
||||||
/* Enumerated values 256-65535 may be used by others subject to */
|
/* Enumerated values 256-65535 may be used by others subject to */
|
||||||
/* procedures and constraints described in Clause 23. */
|
/* procedures and constraints described in Clause 23. */
|
||||||
} BACNET_LIFE_SAFETY_STATE;
|
} BACNET_LIFE_SAFETY_STATE;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -1035,8 +1035,8 @@ typedef enum {
|
|||||||
NETWORK_MESSAGE_INITIALIZE_ROUTING_TABLE_ACK = 7,
|
NETWORK_MESSAGE_INITIALIZE_ROUTING_TABLE_ACK = 7,
|
||||||
NETWORK_MESSAGE_ESTABLISH_CONNECTION_TO_NETWORK = 8,
|
NETWORK_MESSAGE_ESTABLISH_CONNECTION_TO_NETWORK = 8,
|
||||||
NETWORK_MESSAGE_DISCONNECT_CONNECTION_TO_NETWORK = 9,
|
NETWORK_MESSAGE_DISCONNECT_CONNECTION_TO_NETWORK = 9,
|
||||||
/* X'0A' to X'7F': Reserved for use by ASHRAE, */
|
/* X'0A' to X'7F': Reserved for use by ASHRAE, */
|
||||||
/* X'80' to X'FF': Available for vendor proprietary messages */
|
/* X'80' to X'FF': Available for vendor proprietary messages */
|
||||||
NETWORK_MESSAGE_INVALID = 0x100
|
NETWORK_MESSAGE_INVALID = 0x100
|
||||||
} BACNET_NETWORK_MESSAGE_TYPE;
|
} BACNET_NETWORK_MESSAGE_TYPE;
|
||||||
|
|
||||||
@@ -1221,21 +1221,21 @@ typedef enum BACnetShedState {
|
|||||||
} BACNET_SHED_STATE;
|
} BACNET_SHED_STATE;
|
||||||
|
|
||||||
typedef enum BACnetLightingOperation {
|
typedef enum BACnetLightingOperation {
|
||||||
BACNET_LIGHTS_STOP = 0,
|
BACNET_LIGHTS_STOP = 0,
|
||||||
BACNET_LIGHTS_FADE_TO = 1,
|
BACNET_LIGHTS_FADE_TO = 1,
|
||||||
BACNET_LIGHTS_FADE_TO_OVER = 2,
|
BACNET_LIGHTS_FADE_TO_OVER = 2,
|
||||||
BACNET_LIGHTS_RAMP_TO = 3,
|
BACNET_LIGHTS_RAMP_TO = 3,
|
||||||
BACNET_LIGHTS_RAMP_TO_AT_RATE = 4,
|
BACNET_LIGHTS_RAMP_TO_AT_RATE = 4,
|
||||||
BACNET_LIGHTS_RAMP_UP = 5,
|
BACNET_LIGHTS_RAMP_UP = 5,
|
||||||
BACNET_LIGHTS_RAMP_UP_AT_RATE = 6,
|
BACNET_LIGHTS_RAMP_UP_AT_RATE = 6,
|
||||||
BACNET_LIGHTS_RAMP_DOWN = 7,
|
BACNET_LIGHTS_RAMP_DOWN = 7,
|
||||||
BACNET_LIGHTS_RAMP_DOWN_AT_RATE = 8,
|
BACNET_LIGHTS_RAMP_DOWN_AT_RATE = 8,
|
||||||
BACNET_LIGHTS_STEP_UP = 9,
|
BACNET_LIGHTS_STEP_UP = 9,
|
||||||
BACNET_LIGHTS_STEP_DOWN = 10,
|
BACNET_LIGHTS_STEP_DOWN = 10,
|
||||||
BACNET_LIGHTS_STEP_UP_BY = 11,
|
BACNET_LIGHTS_STEP_UP_BY = 11,
|
||||||
BACNET_LIGHTS_STEP_DOWN_BY = 12,
|
BACNET_LIGHTS_STEP_DOWN_BY = 12,
|
||||||
BACNET_LIGHTS_GOTO_LEVEL = 13,
|
BACNET_LIGHTS_GOTO_LEVEL = 13,
|
||||||
BACNET_LIGHTS_RELINQUISH = 14
|
BACNET_LIGHTS_RELINQUISH = 14
|
||||||
} BACNET_LIGHTING_OPERATION;
|
} BACNET_LIGHTING_OPERATION;
|
||||||
|
|
||||||
/* NOTE: BACNET_DAYS_OF_WEEK is different than BACNET_WEEKDAY */
|
/* NOTE: BACNET_DAYS_OF_WEEK is different than BACNET_WEEKDAY */
|
||||||
@@ -1247,7 +1247,7 @@ typedef enum BACnetDaysOfWeek {
|
|||||||
BACNET_DAYS_OF_WEEK_THURSDAY = 3,
|
BACNET_DAYS_OF_WEEK_THURSDAY = 3,
|
||||||
BACNET_DAYS_OF_WEEK_FRIDAY = 4,
|
BACNET_DAYS_OF_WEEK_FRIDAY = 4,
|
||||||
BACNET_DAYS_OF_WEEK_SATURDAY = 5,
|
BACNET_DAYS_OF_WEEK_SATURDAY = 5,
|
||||||
BACNET_DAYS_OF_WEEK_SUNDAY = 6
|
BACNET_DAYS_OF_WEEK_SUNDAY = 6
|
||||||
} BACNET_DAYS_OF_WEEK;
|
} BACNET_DAYS_OF_WEEK;
|
||||||
|
|
||||||
#endif /* end of BACENUM_H */
|
#endif /* end of BACENUM_H */
|
||||||
|
|||||||
@@ -40,35 +40,44 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
int bacerror_encode_apdu(uint8_t * apdu,
|
int bacerror_encode_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
uint8_t invoke_id,
|
uint8_t invoke_id,
|
||||||
BACNET_CONFIRMED_SERVICE service,
|
BACNET_CONFIRMED_SERVICE service,
|
||||||
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code);
|
BACNET_ERROR_CLASS error_class,
|
||||||
|
BACNET_ERROR_CODE error_code);
|
||||||
|
|
||||||
int bacerror_decode_service_request(uint8_t * apdu,
|
int bacerror_decode_service_request(
|
||||||
|
uint8_t * apdu,
|
||||||
unsigned apdu_len,
|
unsigned apdu_len,
|
||||||
uint8_t * invoke_id,
|
uint8_t * invoke_id,
|
||||||
BACNET_CONFIRMED_SERVICE * service,
|
BACNET_CONFIRMED_SERVICE * service,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
int bacerror_decode_error_class_and_code(uint8_t * apdu,
|
int bacerror_decode_error_class_and_code(
|
||||||
|
uint8_t * apdu,
|
||||||
unsigned apdu_len,
|
unsigned apdu_len,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
int bacerror_decode_apdu(uint8_t * apdu,
|
int bacerror_decode_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
unsigned apdu_len,
|
unsigned apdu_len,
|
||||||
uint8_t * invoke_id,
|
uint8_t * invoke_id,
|
||||||
BACNET_CONFIRMED_SERVICE * service,
|
BACNET_CONFIRMED_SERVICE * service,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
void testBACError(Test * pTest);
|
void testBACError(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,40 +44,52 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void BACfile_Property_Lists(
|
void BACfile_Property_Lists(
|
||||||
const int **pRequired,
|
const int **pRequired,
|
||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary);
|
const int **pProprietary);
|
||||||
char *bacfile_name(uint32_t instance);
|
char *bacfile_name(
|
||||||
bool bacfile_valid_instance(uint32_t object_instance);
|
uint32_t instance);
|
||||||
uint32_t bacfile_count(void);
|
bool bacfile_valid_instance(
|
||||||
uint32_t bacfile_index_to_instance(unsigned find_index);
|
uint32_t object_instance);
|
||||||
uint32_t bacfile_instance(char *filename);
|
uint32_t bacfile_count(
|
||||||
|
void);
|
||||||
|
uint32_t bacfile_index_to_instance(
|
||||||
|
unsigned find_index);
|
||||||
|
uint32_t bacfile_instance(
|
||||||
|
char *filename);
|
||||||
/* this is one way to match up the invoke ID with */
|
/* this is one way to match up the invoke ID with */
|
||||||
/* the file ID from the AtomicReadFile request. */
|
/* the file ID from the AtomicReadFile request. */
|
||||||
/* Another way would be to store the */
|
/* Another way would be to store the */
|
||||||
/* invokeID and file instance in a list or table */
|
/* invokeID and file instance in a list or table */
|
||||||
/* when the request was sent */
|
/* when the request was sent */
|
||||||
uint32_t bacfile_instance_from_tsm(uint8_t invokeID);
|
uint32_t bacfile_instance_from_tsm(
|
||||||
|
uint8_t invokeID);
|
||||||
|
|
||||||
/* handler ACK helper */
|
/* handler ACK helper */
|
||||||
bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA * data);
|
bool bacfile_read_data(
|
||||||
bool bacfile_write_stream_data(BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
BACNET_ATOMIC_READ_FILE_DATA * data);
|
||||||
|
bool bacfile_write_stream_data(
|
||||||
|
BACNET_ATOMIC_WRITE_FILE_DATA * data);
|
||||||
|
|
||||||
/* handling for read property service */
|
/* handling for read property service */
|
||||||
int bacfile_encode_property_apdu(uint8_t * apdu,
|
int bacfile_encode_property_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
int32_t array_index,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
/* handling for write property service */
|
/* handling for write property service */
|
||||||
bool bacfile_write_property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool bacfile_write_property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -40,29 +40,55 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/* unsigned value encoding and decoding */
|
/* unsigned value encoding and decoding */
|
||||||
int encode_unsigned16(uint8_t * apdu, uint16_t value);
|
int encode_unsigned16(
|
||||||
int decode_unsigned16(uint8_t * apdu, uint16_t * value);
|
uint8_t * apdu,
|
||||||
int encode_unsigned24(uint8_t * apdu, uint32_t value);
|
uint16_t value);
|
||||||
int decode_unsigned24(uint8_t * apdu, uint32_t * value);
|
int decode_unsigned16(
|
||||||
int encode_unsigned32(uint8_t * apdu, uint32_t value);
|
uint8_t * apdu,
|
||||||
int decode_unsigned32(uint8_t * apdu, uint32_t * value);
|
uint16_t * value);
|
||||||
|
int encode_unsigned24(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint32_t value);
|
||||||
|
int decode_unsigned24(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint32_t * value);
|
||||||
|
int encode_unsigned32(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint32_t value);
|
||||||
|
int decode_unsigned32(
|
||||||
|
uint8_t * apdu,
|
||||||
|
uint32_t * value);
|
||||||
|
|
||||||
/* signed value encoding and decoding */
|
/* signed value encoding and decoding */
|
||||||
int encode_signed8(uint8_t * apdu, int8_t value);
|
int encode_signed8(
|
||||||
int decode_signed8(uint8_t * apdu, int32_t * value);
|
uint8_t * apdu,
|
||||||
int encode_signed16(uint8_t * apdu, int16_t value);
|
int8_t value);
|
||||||
int decode_signed16(uint8_t * apdu, int32_t * value);
|
int decode_signed8(
|
||||||
int encode_signed24(uint8_t * apdu, int32_t value);
|
uint8_t * apdu,
|
||||||
int decode_signed24(uint8_t * apdu, int32_t * value);
|
int32_t * value);
|
||||||
int encode_signed32(uint8_t * apdu, int32_t value);
|
int encode_signed16(
|
||||||
int decode_signed32(uint8_t * apdu, int32_t * value);
|
uint8_t * apdu,
|
||||||
|
int16_t value);
|
||||||
|
int decode_signed16(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int32_t * value);
|
||||||
|
int encode_signed24(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int32_t value);
|
||||||
|
int decode_signed24(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int32_t * value);
|
||||||
|
int encode_signed32(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int32_t value);
|
||||||
|
int decode_signed32(
|
||||||
|
uint8_t * apdu,
|
||||||
|
int32_t * value);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -39,20 +39,24 @@
|
|||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
signed prop_id; /* index number that matches the text */
|
signed prop_id; /* index number that matches the text */
|
||||||
signed tag_id; /* text pair - use NULL to end the list */
|
signed tag_id; /* text pair - use NULL to end the list */
|
||||||
} PROP_TAG_DATA;
|
} PROP_TAG_DATA;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
signed bacprop_tag_by_index_default(PROP_TAG_DATA * data_list,
|
signed bacprop_tag_by_index_default(
|
||||||
signed index, signed default_ret);
|
PROP_TAG_DATA * data_list,
|
||||||
|
signed index,
|
||||||
|
signed default_ret);
|
||||||
|
|
||||||
signed bacprop_property_tag(BACNET_OBJECT_TYPE type, signed prop);
|
signed bacprop_property_tag(
|
||||||
|
BACNET_OBJECT_TYPE type,
|
||||||
|
signed prop);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -40,20 +40,23 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
int decode_real(uint8_t * apdu, float *real_value);
|
int decode_real(
|
||||||
int encode_bacnet_real(float value, uint8_t * apdu);
|
uint8_t * apdu,
|
||||||
|
float *real_value);
|
||||||
|
int encode_bacnet_real(
|
||||||
|
float value,
|
||||||
|
uint8_t * apdu);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void testBACreal(Test * pTest);
|
void testBACreal(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -65,23 +65,36 @@ typedef struct BACnet_Octet_String {
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void bitstring_init(BACNET_BIT_STRING * bit_string);
|
void bitstring_init(
|
||||||
void bitstring_set_bit(BACNET_BIT_STRING * bit_string, uint8_t bit_number,
|
BACNET_BIT_STRING * bit_string);
|
||||||
|
void bitstring_set_bit(
|
||||||
|
BACNET_BIT_STRING * bit_string,
|
||||||
|
uint8_t bit_number,
|
||||||
bool value);
|
bool value);
|
||||||
bool bitstring_bit(BACNET_BIT_STRING * bit_string, uint8_t bit_number);
|
bool bitstring_bit(
|
||||||
uint8_t bitstring_bits_used(BACNET_BIT_STRING * bit_string);
|
BACNET_BIT_STRING * bit_string,
|
||||||
|
uint8_t bit_number);
|
||||||
|
uint8_t bitstring_bits_used(
|
||||||
|
BACNET_BIT_STRING * bit_string);
|
||||||
/* returns the number of bytes that a bit string is using */
|
/* returns the number of bytes that a bit string is using */
|
||||||
int bitstring_bytes_used(BACNET_BIT_STRING * bit_string);
|
int bitstring_bytes_used(
|
||||||
uint8_t bitstring_bits_capacity(BACNET_BIT_STRING * bit_string);
|
BACNET_BIT_STRING * bit_string);
|
||||||
|
uint8_t bitstring_bits_capacity(
|
||||||
|
BACNET_BIT_STRING * bit_string);
|
||||||
/* used for encoding and decoding from the APDU */
|
/* used for encoding and decoding from the APDU */
|
||||||
uint8_t bitstring_octet(BACNET_BIT_STRING * bit_string,
|
uint8_t bitstring_octet(
|
||||||
|
BACNET_BIT_STRING * bit_string,
|
||||||
uint8_t octet_index);
|
uint8_t octet_index);
|
||||||
bool bitstring_set_octet(BACNET_BIT_STRING * bit_string, uint8_t index,
|
bool bitstring_set_octet(
|
||||||
|
BACNET_BIT_STRING * bit_string,
|
||||||
|
uint8_t index,
|
||||||
uint8_t octet);
|
uint8_t octet);
|
||||||
bool bitstring_set_bits_used(BACNET_BIT_STRING * bit_string,
|
bool bitstring_set_bits_used(
|
||||||
uint8_t bytes_used, uint8_t unused_bits);
|
BACNET_BIT_STRING * bit_string,
|
||||||
|
uint8_t bytes_used,
|
||||||
|
uint8_t unused_bits);
|
||||||
bool bitstring_copy(
|
bool bitstring_copy(
|
||||||
BACNET_BIT_STRING * dest,
|
BACNET_BIT_STRING * dest,
|
||||||
BACNET_BIT_STRING * src);
|
BACNET_BIT_STRING * src);
|
||||||
@@ -89,57 +102,80 @@ extern "C" {
|
|||||||
|
|
||||||
/* returns false if the string exceeds capacity
|
/* returns false if the string exceeds capacity
|
||||||
initialize by using length=0 */
|
initialize by using length=0 */
|
||||||
bool characterstring_init(BACNET_CHARACTER_STRING * char_string,
|
bool characterstring_init(
|
||||||
uint8_t encoding, char *value, size_t length);
|
BACNET_CHARACTER_STRING * char_string,
|
||||||
|
uint8_t encoding,
|
||||||
|
char *value,
|
||||||
|
size_t length);
|
||||||
/* used for ANSI C-Strings */
|
/* used for ANSI C-Strings */
|
||||||
bool characterstring_init_ansi(BACNET_CHARACTER_STRING * char_string,
|
bool characterstring_init_ansi(
|
||||||
|
BACNET_CHARACTER_STRING * char_string,
|
||||||
char *value);
|
char *value);
|
||||||
bool characterstring_copy(BACNET_CHARACTER_STRING * dest,
|
bool characterstring_copy(
|
||||||
|
BACNET_CHARACTER_STRING * dest,
|
||||||
BACNET_CHARACTER_STRING * src);
|
BACNET_CHARACTER_STRING * src);
|
||||||
/* returns true if the strings are the same length, encoding, value */
|
/* returns true if the strings are the same length, encoding, value */
|
||||||
bool characterstring_same(BACNET_CHARACTER_STRING * dest,
|
bool characterstring_same(
|
||||||
|
BACNET_CHARACTER_STRING * dest,
|
||||||
BACNET_CHARACTER_STRING * src);
|
BACNET_CHARACTER_STRING * src);
|
||||||
bool characterstring_ansi_same(BACNET_CHARACTER_STRING * dest,
|
bool characterstring_ansi_same(
|
||||||
|
BACNET_CHARACTER_STRING * dest,
|
||||||
const char *src);
|
const char *src);
|
||||||
/* returns false if the string exceeds capacity */
|
/* returns false if the string exceeds capacity */
|
||||||
bool characterstring_append(BACNET_CHARACTER_STRING * char_string,
|
bool characterstring_append(
|
||||||
char *value, size_t length);
|
BACNET_CHARACTER_STRING * char_string,
|
||||||
|
char *value,
|
||||||
|
size_t length);
|
||||||
/* This function sets a new length without changing the value.
|
/* This function sets a new length without changing the value.
|
||||||
If length exceeds capacity, no modification happens and
|
If length exceeds capacity, no modification happens and
|
||||||
function returns false. */
|
function returns false. */
|
||||||
bool characterstring_truncate(BACNET_CHARACTER_STRING * char_string,
|
bool characterstring_truncate(
|
||||||
|
BACNET_CHARACTER_STRING * char_string,
|
||||||
size_t length);
|
size_t length);
|
||||||
bool characterstring_set_encoding(BACNET_CHARACTER_STRING *
|
bool characterstring_set_encoding(
|
||||||
char_string, uint8_t encoding);
|
BACNET_CHARACTER_STRING * char_string,
|
||||||
|
uint8_t encoding);
|
||||||
/* Returns the value */
|
/* Returns the value */
|
||||||
char *characterstring_value(BACNET_CHARACTER_STRING * char_string);
|
char *characterstring_value(
|
||||||
|
BACNET_CHARACTER_STRING * char_string);
|
||||||
/* returns the length */
|
/* returns the length */
|
||||||
size_t characterstring_length(BACNET_CHARACTER_STRING * char_string);
|
size_t characterstring_length(
|
||||||
uint8_t characterstring_encoding(BACNET_CHARACTER_STRING *
|
BACNET_CHARACTER_STRING * char_string);
|
||||||
char_string);
|
uint8_t characterstring_encoding(
|
||||||
size_t characterstring_capacity(BACNET_CHARACTER_STRING * char_string);
|
BACNET_CHARACTER_STRING * char_string);
|
||||||
|
size_t characterstring_capacity(
|
||||||
|
BACNET_CHARACTER_STRING * char_string);
|
||||||
|
|
||||||
/* returns false if the string exceeds capacity
|
/* returns false if the string exceeds capacity
|
||||||
initialize by using length=0 */
|
initialize by using length=0 */
|
||||||
bool octetstring_init(BACNET_OCTET_STRING * octet_string,
|
bool octetstring_init(
|
||||||
uint8_t * value, size_t length);
|
BACNET_OCTET_STRING * octet_string,
|
||||||
bool octetstring_copy(BACNET_OCTET_STRING * dest,
|
uint8_t * value,
|
||||||
|
size_t length);
|
||||||
|
bool octetstring_copy(
|
||||||
|
BACNET_OCTET_STRING * dest,
|
||||||
BACNET_OCTET_STRING * src);
|
BACNET_OCTET_STRING * src);
|
||||||
/* returns false if the string exceeds capacity */
|
/* returns false if the string exceeds capacity */
|
||||||
bool octetstring_append(BACNET_OCTET_STRING * octet_string,
|
bool octetstring_append(
|
||||||
uint8_t * value, size_t length);
|
BACNET_OCTET_STRING * octet_string,
|
||||||
|
uint8_t * value,
|
||||||
|
size_t length);
|
||||||
/* This function sets a new length without changing the value.
|
/* This function sets a new length without changing the value.
|
||||||
If length exceeds capacity, no modification happens and
|
If length exceeds capacity, no modification happens and
|
||||||
function returns false. */
|
function returns false. */
|
||||||
bool octetstring_truncate(BACNET_OCTET_STRING * octet_string,
|
bool octetstring_truncate(
|
||||||
|
BACNET_OCTET_STRING * octet_string,
|
||||||
size_t length);
|
size_t length);
|
||||||
/* Returns the value */
|
/* Returns the value */
|
||||||
uint8_t *octetstring_value(BACNET_OCTET_STRING * octet_string);
|
uint8_t *octetstring_value(
|
||||||
|
BACNET_OCTET_STRING * octet_string);
|
||||||
/* Returns the length.*/
|
/* Returns the length.*/
|
||||||
size_t octetstring_length(BACNET_OCTET_STRING * octet_string);
|
size_t octetstring_length(
|
||||||
size_t octetstring_capacity(BACNET_OCTET_STRING * octet_string);
|
BACNET_OCTET_STRING * octet_string);
|
||||||
|
size_t octetstring_capacity(
|
||||||
|
BACNET_OCTET_STRING * octet_string);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -51,31 +51,50 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
const char *bactext_confirmed_service_name(int index);
|
const char *bactext_confirmed_service_name(
|
||||||
const char *bactext_unconfirmed_service_name(int index);
|
int index);
|
||||||
const char *bactext_application_tag_name(int index);
|
const char *bactext_unconfirmed_service_name(
|
||||||
const char *bactext_object_type_name(int index);
|
int index);
|
||||||
const char *bactext_property_name(int index);
|
const char *bactext_application_tag_name(
|
||||||
const char *bactext_engineering_unit_name(int index);
|
int index);
|
||||||
const char *bactext_reject_reason_name(int index);
|
const char *bactext_object_type_name(
|
||||||
const char *bactext_abort_reason_name(int index);
|
int index);
|
||||||
const char *bactext_error_class_name(int index);
|
const char *bactext_property_name(
|
||||||
const char *bactext_error_code_name(int index);
|
int index);
|
||||||
unsigned bactext_property_id(const char *name);
|
const char *bactext_engineering_unit_name(
|
||||||
const char *bactext_month_name(int index);
|
int index);
|
||||||
const char *bactext_week_of_month_name(int index);
|
const char *bactext_reject_reason_name(
|
||||||
const char *bactext_day_of_week_name(int index);
|
int index);
|
||||||
const char *bactext_event_state_name(int index);
|
const char *bactext_abort_reason_name(
|
||||||
const char *bactext_binary_present_value_name(int index);
|
int index);
|
||||||
const char *bactext_reliability_name(int index);
|
const char *bactext_error_class_name(
|
||||||
const char *bactext_device_status_name(int index);
|
int index);
|
||||||
const char *bactext_segmentation_name(int index);
|
const char *bactext_error_code_name(
|
||||||
|
int index);
|
||||||
|
unsigned bactext_property_id(
|
||||||
|
const char *name);
|
||||||
|
const char *bactext_month_name(
|
||||||
|
int index);
|
||||||
|
const char *bactext_week_of_month_name(
|
||||||
|
int index);
|
||||||
|
const char *bactext_day_of_week_name(
|
||||||
|
int index);
|
||||||
|
const char *bactext_event_state_name(
|
||||||
|
int index);
|
||||||
|
const char *bactext_binary_present_value_name(
|
||||||
|
int index);
|
||||||
|
const char *bactext_reliability_name(
|
||||||
|
int index);
|
||||||
|
const char *bactext_device_status_name(
|
||||||
|
int index);
|
||||||
|
const char *bactext_segmentation_name(
|
||||||
|
int index);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif /* BACTEXT_PRINT_ENABLED */
|
#endif /* BACTEXT_PRINT_ENABLED */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -31,29 +31,36 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void Binary_Input_Property_Lists(
|
void Binary_Input_Property_Lists(
|
||||||
const int **pRequired,
|
const int **pRequired,
|
||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary);
|
const int **pProprietary);
|
||||||
bool Binary_Input_Valid_Instance(uint32_t object_instance);
|
bool Binary_Input_Valid_Instance(
|
||||||
unsigned Binary_Input_Count(void);
|
uint32_t object_instance);
|
||||||
uint32_t Binary_Input_Index_To_Instance(unsigned index);
|
unsigned Binary_Input_Count(
|
||||||
char *Binary_Input_Name(uint32_t object_instance);
|
void);
|
||||||
|
uint32_t Binary_Input_Index_To_Instance(
|
||||||
|
unsigned index);
|
||||||
|
char *Binary_Input_Name(
|
||||||
|
uint32_t object_instance);
|
||||||
|
|
||||||
int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
|
int Binary_Input_Encode_Property_APDU(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
int32_t array_index,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testBinaryInput(Test * pTest);
|
void testBinaryInput(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/* Big-Endian systems save the most significant byte first. */
|
/* Big-Endian systems save the most significant byte first. */
|
||||||
/* Sun and Motorola processors, IBM-370s and PDP-10s are big-endian. */
|
/* Sun and Motorola processors, IBM-370s and PDP-10s are big-endian. */
|
||||||
@@ -21,9 +21,10 @@ extern "C" {
|
|||||||
/* x[2] = 0x03 */
|
/* x[2] = 0x03 */
|
||||||
/* x[3] = 0x04 */
|
/* x[3] = 0x04 */
|
||||||
|
|
||||||
int big_endian(void);
|
int big_endian(
|
||||||
|
void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+34
-19
@@ -51,51 +51,66 @@ extern bool BIP_Debug;
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/* note: define init and cleanup in your ports section */
|
/* note: define init and cleanup in your ports section */
|
||||||
/* on Linux, ifname is eth0, ath0, arc0, and others.
|
/* on Linux, ifname is eth0, ath0, arc0, and others.
|
||||||
on Windows, ifname is the dotted ip address of the interface */
|
on Windows, ifname is the dotted ip address of the interface */
|
||||||
bool bip_init(char *ifname);
|
bool bip_init(
|
||||||
|
char *ifname);
|
||||||
|
|
||||||
/* normal functions... */
|
/* normal functions... */
|
||||||
void bip_cleanup(void);
|
void bip_cleanup(
|
||||||
void bip_set_socket(int sock_fd);
|
void);
|
||||||
int bip_socket(void);
|
void bip_set_socket(
|
||||||
bool bip_valid(void);
|
int sock_fd);
|
||||||
void bip_get_broadcast_address(BACNET_ADDRESS * dest); /* destination address */
|
int bip_socket(
|
||||||
void bip_get_my_address(BACNET_ADDRESS * my_address);
|
void);
|
||||||
|
bool bip_valid(
|
||||||
|
void);
|
||||||
|
void bip_get_broadcast_address(
|
||||||
|
BACNET_ADDRESS * dest); /* destination address */
|
||||||
|
void bip_get_my_address(
|
||||||
|
BACNET_ADDRESS * my_address);
|
||||||
|
|
||||||
/* function to send a packet out the BACnet/IP socket */
|
/* function to send a packet out the BACnet/IP socket */
|
||||||
/* returns zero on success, non-zero on failure */
|
/* returns zero on success, non-zero on failure */
|
||||||
int bip_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
int bip_send_pdu(
|
||||||
|
BACNET_ADDRESS * dest, /* destination address */
|
||||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||||
uint8_t * pdu, /* any data to be sent - may be null */
|
uint8_t * pdu, /* any data to be sent - may be null */
|
||||||
unsigned pdu_len); /* number of bytes of data */
|
unsigned pdu_len); /* number of bytes of data */
|
||||||
|
|
||||||
/* receives a BACnet/IP packet */
|
/* receives a BACnet/IP packet */
|
||||||
/* returns the number of octets in the PDU, or zero on failure */
|
/* returns the number of octets in the PDU, or zero on failure */
|
||||||
uint16_t bip_receive(BACNET_ADDRESS * src, /* source address */
|
uint16_t bip_receive(
|
||||||
uint8_t * pdu, /* PDU data */
|
BACNET_ADDRESS * src, /* source address */
|
||||||
|
uint8_t * pdu, /* PDU data */
|
||||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||||
unsigned timeout); /* milliseconds to wait for a packet */
|
unsigned timeout); /* milliseconds to wait for a packet */
|
||||||
|
|
||||||
/* use host byte order for setting */
|
/* use host byte order for setting */
|
||||||
void bip_set_port(uint16_t port);
|
void bip_set_port(
|
||||||
|
uint16_t port);
|
||||||
/* returns host byte order */
|
/* returns host byte order */
|
||||||
uint16_t bip_get_port(void);
|
uint16_t bip_get_port(
|
||||||
|
void);
|
||||||
|
|
||||||
/* use network byte order for setting */
|
/* use network byte order for setting */
|
||||||
void bip_set_addr(uint32_t net_address);
|
void bip_set_addr(
|
||||||
|
uint32_t net_address);
|
||||||
/* returns host byte order */
|
/* returns host byte order */
|
||||||
uint32_t bip_get_addr(void);
|
uint32_t bip_get_addr(
|
||||||
|
void);
|
||||||
|
|
||||||
/* use network byte order for setting */
|
/* use network byte order for setting */
|
||||||
void bip_set_broadcast_addr(uint32_t net_address);
|
void bip_set_broadcast_addr(
|
||||||
|
uint32_t net_address);
|
||||||
/* returns host byte order */
|
/* returns host byte order */
|
||||||
uint32_t bip_get_broadcast_addr(void);
|
uint32_t bip_get_broadcast_addr(
|
||||||
|
void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+20
-11
@@ -33,32 +33,41 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void Binary_Output_Property_Lists(
|
void Binary_Output_Property_Lists(
|
||||||
const int **pRequired,
|
const int **pRequired,
|
||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary);
|
const int **pProprietary);
|
||||||
bool Binary_Output_Valid_Instance(uint32_t object_instance);
|
bool Binary_Output_Valid_Instance(
|
||||||
unsigned Binary_Output_Count(void);
|
uint32_t object_instance);
|
||||||
uint32_t Binary_Output_Index_To_Instance(unsigned index);
|
unsigned Binary_Output_Count(
|
||||||
char *Binary_Output_Name(uint32_t object_instance);
|
void);
|
||||||
|
uint32_t Binary_Output_Index_To_Instance(
|
||||||
|
unsigned index);
|
||||||
|
char *Binary_Output_Name(
|
||||||
|
uint32_t object_instance);
|
||||||
|
|
||||||
int Binary_Output_Encode_Property_APDU(uint8_t * apdu,
|
int Binary_Output_Encode_Property_APDU(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
int32_t array_index,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
bool Binary_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Binary_Output_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testBinaryOutput(Test * pTest);
|
void testBinaryOutput(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+20
-11
@@ -33,32 +33,41 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void Binary_Value_Property_Lists(
|
void Binary_Value_Property_Lists(
|
||||||
const int **pRequired,
|
const int **pRequired,
|
||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary);
|
const int **pProprietary);
|
||||||
bool Binary_Value_Valid_Instance(uint32_t object_instance);
|
bool Binary_Value_Valid_Instance(
|
||||||
unsigned Binary_Value_Count(void);
|
uint32_t object_instance);
|
||||||
uint32_t Binary_Value_Index_To_Instance(unsigned index);
|
unsigned Binary_Value_Count(
|
||||||
char *Binary_Value_Name(uint32_t object_instance);
|
void);
|
||||||
|
uint32_t Binary_Value_Index_To_Instance(
|
||||||
|
unsigned index);
|
||||||
|
char *Binary_Value_Name(
|
||||||
|
uint32_t object_instance);
|
||||||
|
|
||||||
int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
|
int Binary_Value_Encode_Property_APDU(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
int32_t array_index,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Binary_Value_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testBinary_Value(Test * pTest);
|
void testBinary_Value(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -43,21 +43,21 @@
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
uint16_t bvlc_receive(
|
uint16_t bvlc_receive(
|
||||||
BACNET_ADDRESS * src, /* returns the source address */
|
BACNET_ADDRESS * src, /* returns the source address */
|
||||||
uint8_t * npdu, /* returns the NPDU */
|
uint8_t * npdu, /* returns the NPDU */
|
||||||
uint16_t max_npdu, /* amount of space available in the NPDU */
|
uint16_t max_npdu, /* amount of space available in the NPDU */
|
||||||
unsigned timeout); /* number of milliseconds to wait for a packet */
|
unsigned timeout); /* number of milliseconds to wait for a packet */
|
||||||
|
|
||||||
int bvlc_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
int bvlc_send_pdu(
|
||||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
BACNET_ADDRESS * dest, /* destination address */
|
||||||
uint8_t * pdu, /* any data to be sent - may be null */
|
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||||
|
uint8_t * pdu, /* any data to be sent - may be null */
|
||||||
unsigned pdu_len);
|
unsigned pdu_len);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif /* */
|
#endif /* */
|
||||||
|
|
||||||
|
|||||||
@@ -67,4 +67,4 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* end of header file */
|
#endif /* end of header file */
|
||||||
|
|||||||
@@ -35,56 +35,81 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/* unconfirmed requests */
|
/* unconfirmed requests */
|
||||||
void Send_WhoIs(int32_t low_limit, int32_t high_limit);
|
void Send_WhoIs(
|
||||||
|
int32_t low_limit,
|
||||||
|
int32_t high_limit);
|
||||||
|
|
||||||
void Send_WhoHas_Object(int32_t low_limit,
|
void Send_WhoHas_Object(
|
||||||
|
int32_t low_limit,
|
||||||
int32_t high_limit,
|
int32_t high_limit,
|
||||||
BACNET_OBJECT_TYPE object_type, uint32_t object_instance);
|
|
||||||
|
|
||||||
void Send_WhoHas_Name(int32_t low_limit,
|
|
||||||
int32_t high_limit, char *object_name);
|
|
||||||
|
|
||||||
void Send_I_Have(uint32_t device_id,
|
|
||||||
BACNET_OBJECT_TYPE object_type,
|
BACNET_OBJECT_TYPE object_type,
|
||||||
uint32_t object_instance, char *object_name);
|
uint32_t object_instance);
|
||||||
|
|
||||||
/* returns the invoke ID for confirmed request, or 0 if failed */
|
void Send_WhoHas_Name(
|
||||||
uint8_t Send_Read_Property_Request(uint32_t device_id, /* destination device */
|
int32_t low_limit,
|
||||||
|
int32_t high_limit,
|
||||||
|
char *object_name);
|
||||||
|
|
||||||
|
void Send_I_Have(
|
||||||
|
uint32_t device_id,
|
||||||
BACNET_OBJECT_TYPE object_type,
|
BACNET_OBJECT_TYPE object_type,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID object_property, int32_t array_index);
|
char *object_name);
|
||||||
|
|
||||||
/* returns the invoke ID for confirmed request, or 0 if failed */
|
/* returns the invoke ID for confirmed request, or 0 if failed */
|
||||||
uint8_t Send_Write_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);
|
||||||
|
|
||||||
|
/* returns the invoke ID for confirmed request, or 0 if failed */
|
||||||
|
uint8_t Send_Write_Property_Request(
|
||||||
|
uint32_t device_id, /* destination device */
|
||||||
BACNET_OBJECT_TYPE object_type,
|
BACNET_OBJECT_TYPE object_type,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID object_property,
|
BACNET_PROPERTY_ID object_property,
|
||||||
BACNET_APPLICATION_DATA_VALUE * object_value,
|
BACNET_APPLICATION_DATA_VALUE * object_value,
|
||||||
uint8_t priority, int32_t array_index);
|
uint8_t priority,
|
||||||
|
int32_t array_index);
|
||||||
|
|
||||||
/* returns the invoke ID for confirmed request, or 0 if failed */
|
/* returns the invoke ID for confirmed request, or 0 if failed */
|
||||||
uint8_t Send_Reinitialize_Device_Request(uint32_t device_id,
|
uint8_t Send_Reinitialize_Device_Request(
|
||||||
BACNET_REINITIALIZED_STATE state, char *password);
|
uint32_t device_id,
|
||||||
|
BACNET_REINITIALIZED_STATE state,
|
||||||
|
char *password);
|
||||||
|
|
||||||
/* returns the invoke ID for confirmed request, or 0 if failed */
|
/* returns the invoke ID for confirmed request, or 0 if failed */
|
||||||
uint8_t Send_Device_Communication_Control_Request(uint32_t device_id, uint16_t timeDuration, /* 0=optional */
|
uint8_t Send_Device_Communication_Control_Request(
|
||||||
BACNET_COMMUNICATION_ENABLE_DISABLE state, char *password); /* NULL=optional */
|
uint32_t device_id,
|
||||||
|
uint16_t timeDuration, /* 0=optional */
|
||||||
|
BACNET_COMMUNICATION_ENABLE_DISABLE state,
|
||||||
|
char *password); /* NULL=optional */
|
||||||
|
|
||||||
void Send_TimeSync(BACNET_DATE * bdate, BACNET_TIME * btime);
|
void Send_TimeSync(
|
||||||
void Send_TimeSyncUTC(BACNET_DATE * bdate, BACNET_TIME * btime);
|
BACNET_DATE * bdate,
|
||||||
|
BACNET_TIME * btime);
|
||||||
|
void Send_TimeSyncUTC(
|
||||||
|
BACNET_DATE * bdate,
|
||||||
|
BACNET_TIME * btime);
|
||||||
|
|
||||||
uint8_t Send_Atomic_Read_File_Stream(uint32_t device_id,
|
uint8_t Send_Atomic_Read_File_Stream(
|
||||||
uint32_t file_instance, int fileStartPosition,
|
uint32_t device_id,
|
||||||
unsigned requestedOctetCount);
|
|
||||||
uint8_t Send_Atomic_Write_File_Stream(uint32_t device_id,
|
|
||||||
uint32_t file_instance,
|
uint32_t file_instance,
|
||||||
int fileStartPosition, BACNET_OCTET_STRING * fileData);
|
int fileStartPosition,
|
||||||
|
unsigned requestedOctetCount);
|
||||||
|
uint8_t Send_Atomic_Write_File_Stream(
|
||||||
|
uint32_t device_id,
|
||||||
|
uint32_t file_instance,
|
||||||
|
int fileStartPosition,
|
||||||
|
BACNET_OCTET_STRING * fileData);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,29 +7,29 @@
|
|||||||
/* declare a single physical layer using your compiler define.
|
/* declare a single physical layer using your compiler define.
|
||||||
see datalink.h for possible defines. */
|
see datalink.h for possible defines. */
|
||||||
#if !(defined(BACDL_ETHERNET) || defined(BACDL_ARCNET) || defined(BACDL_MSTP) || defined(BACDL_BIP) || defined(BACDL_TEST))
|
#if !(defined(BACDL_ETHERNET) || defined(BACDL_ARCNET) || defined(BACDL_MSTP) || defined(BACDL_BIP) || defined(BACDL_TEST))
|
||||||
#define BACDL_BIP
|
#define BACDL_BIP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* optional debug info for BACnet/IP datalink layers */
|
/* optional debug info for BACnet/IP datalink layers */
|
||||||
#if defined(BACDL_BIP)
|
#if defined(BACDL_BIP)
|
||||||
#if !defined(USE_INADDR)
|
#if !defined(USE_INADDR)
|
||||||
#define USE_INADDR 1
|
#define USE_INADDR 1
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Define your processor architecture as
|
/* Define your processor architecture as
|
||||||
Big Endian (PowerPC,68K,Sparc) or Little Endian (Intel,AVR)
|
Big Endian (PowerPC,68K,Sparc) or Little Endian (Intel,AVR)
|
||||||
ARM and MIPS can be either - what is your setup? */
|
ARM and MIPS can be either - what is your setup? */
|
||||||
#if !defined(BIG_ENDIAN)
|
#if !defined(BIG_ENDIAN)
|
||||||
#define BIG_ENDIAN 0
|
#define BIG_ENDIAN 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Define your Vendor Identifier assigned by ASHRAE */
|
/* Define your Vendor Identifier assigned by ASHRAE */
|
||||||
#if !defined(BACNET_VENDOR_ID)
|
#if !defined(BACNET_VENDOR_ID)
|
||||||
#define BACNET_VENDOR_ID 260
|
#define BACNET_VENDOR_ID 260
|
||||||
#endif
|
#endif
|
||||||
#if !defined(BACNET_VENDOR_NAME)
|
#if !defined(BACNET_VENDOR_NAME)
|
||||||
#define BACNET_VENDOR_NAME "BACnet Stack at SourceForge"
|
#define BACNET_VENDOR_NAME "BACnet Stack at SourceForge"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Max number of bytes in an APDU. */
|
/* Max number of bytes in an APDU. */
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
/* Lon=206, MS/TP=480, ARCNET=480, Ethernet=1476, BACnet/IP=64K */
|
/* Lon=206, MS/TP=480, ARCNET=480, Ethernet=1476, BACnet/IP=64K */
|
||||||
#if !defined(MAX_APDU)
|
#if !defined(MAX_APDU)
|
||||||
/* #define MAX_APDU 50 */
|
/* #define MAX_APDU 50 */
|
||||||
#define MAX_APDU 480
|
#define MAX_APDU 480
|
||||||
/* #define MAX_APDU 1476 */
|
/* #define MAX_APDU 1476 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
/* Configure from 1..255 for number of outstanding confirmed */
|
/* Configure from 1..255 for number of outstanding confirmed */
|
||||||
/* requests available. */
|
/* requests available. */
|
||||||
#if !defined(MAX_TSM_TRANSACTIONS)
|
#if !defined(MAX_TSM_TRANSACTIONS)
|
||||||
#define MAX_TSM_TRANSACTIONS 255
|
#define MAX_TSM_TRANSACTIONS 255
|
||||||
#endif
|
#endif
|
||||||
/* The address cache is used for binding to BACnet devices */
|
/* The address cache is used for binding to BACnet devices */
|
||||||
/* The number of entries corresponds to the number of */
|
/* The number of entries corresponds to the number of */
|
||||||
@@ -57,30 +57,30 @@
|
|||||||
/* If your device is a simple server and does not need to bind, */
|
/* If your device is a simple server and does not need to bind, */
|
||||||
/* then you don't need to use this. */
|
/* then you don't need to use this. */
|
||||||
#if !defined(MAX_ADDRESS_CACHE)
|
#if !defined(MAX_ADDRESS_CACHE)
|
||||||
#define MAX_ADDRESS_CACHE 255
|
#define MAX_ADDRESS_CACHE 255
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* some modules have debugging enabled using PRINT_ENABLED */
|
/* some modules have debugging enabled using PRINT_ENABLED */
|
||||||
#if !defined(PRINT_ENABLED)
|
#if !defined(PRINT_ENABLED)
|
||||||
#define PRINT_ENABLED 0
|
#define PRINT_ENABLED 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* BACAPP decodes WriteProperty service requests
|
/* BACAPP decodes WriteProperty service requests
|
||||||
Choose the datatypes that your application supports */
|
Choose the datatypes that your application supports */
|
||||||
#if defined (BACAPP_ALL)
|
#if defined (BACAPP_ALL)
|
||||||
#define BACAPP_NULL
|
#define BACAPP_NULL
|
||||||
#define BACAPP_BOOLEAN
|
#define BACAPP_BOOLEAN
|
||||||
#define BACAPP_UNSIGNED
|
#define BACAPP_UNSIGNED
|
||||||
#define BACAPP_SIGNED
|
#define BACAPP_SIGNED
|
||||||
#define BACAPP_REAL
|
#define BACAPP_REAL
|
||||||
/* FIXME: not implemented #define BACAPP_DOUBLE */
|
/* FIXME: not implemented #define BACAPP_DOUBLE */
|
||||||
#define BACAPP_OCTET_STRING
|
#define BACAPP_OCTET_STRING
|
||||||
#define BACAPP_CHARACTER_STRING
|
#define BACAPP_CHARACTER_STRING
|
||||||
#define BACAPP_BIT_STRING
|
#define BACAPP_BIT_STRING
|
||||||
#define BACAPP_ENUMERATED
|
#define BACAPP_ENUMERATED
|
||||||
#define BACAPP_DATE
|
#define BACAPP_DATE
|
||||||
#define BACAPP_TIME
|
#define BACAPP_TIME
|
||||||
#define BACAPP_OBJECT_ID
|
#define BACAPP_OBJECT_ID
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+49
-25
@@ -67,54 +67,78 @@ typedef struct BACnet_Subscribe_COV_Data {
|
|||||||
BACNET_OBJECT_ID monitoredObjectIdentifier;
|
BACNET_OBJECT_ID monitoredObjectIdentifier;
|
||||||
bool cancellationRequest; /* true if this is a cancellation request */
|
bool cancellationRequest; /* true if this is a cancellation request */
|
||||||
bool issueConfirmedNotifications; /* optional */
|
bool issueConfirmedNotifications; /* optional */
|
||||||
unsigned lifetime; /* optional */
|
unsigned lifetime; /* optional */
|
||||||
BACNET_PROPERTY_REFERENCE monitoredProperty;
|
BACNET_PROPERTY_REFERENCE monitoredProperty;
|
||||||
bool covIncrementPresent; /* true if present */
|
bool covIncrementPresent; /* true if present */
|
||||||
float covIncrement; /* optional */
|
float covIncrement; /* optional */
|
||||||
} BACNET_SUBSCRIBE_COV_DATA;
|
} BACNET_SUBSCRIBE_COV_DATA;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
int ucov_notify_encode_apdu(uint8_t * apdu, BACNET_COV_DATA * data);
|
int ucov_notify_encode_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
|
BACNET_COV_DATA * data);
|
||||||
|
|
||||||
int ucov_notify_decode_apdu(uint8_t * apdu,
|
int ucov_notify_decode_apdu(
|
||||||
unsigned apdu_len, BACNET_COV_DATA * data);
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
BACNET_COV_DATA * data);
|
||||||
|
|
||||||
int ucov_notify_send(uint8_t * buffer, BACNET_COV_DATA * data);
|
int ucov_notify_send(
|
||||||
|
uint8_t * buffer,
|
||||||
|
BACNET_COV_DATA * data);
|
||||||
|
|
||||||
int ccov_notify_encode_apdu(uint8_t * apdu,
|
int ccov_notify_encode_apdu(
|
||||||
uint8_t invoke_id, BACNET_COV_DATA * data);
|
uint8_t * apdu,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
BACNET_COV_DATA * data);
|
||||||
|
|
||||||
int ccov_notify_decode_apdu(uint8_t * apdu,
|
int ccov_notify_decode_apdu(
|
||||||
unsigned apdu_len, uint8_t * invoke_id, BACNET_COV_DATA * data);
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
uint8_t * invoke_id,
|
||||||
|
BACNET_COV_DATA * data);
|
||||||
|
|
||||||
/* common for both confirmed and unconfirmed */
|
/* common for both confirmed and unconfirmed */
|
||||||
int cov_notify_decode_service_request(uint8_t * apdu,
|
int cov_notify_decode_service_request(
|
||||||
unsigned apdu_len, BACNET_COV_DATA * data);
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
BACNET_COV_DATA * data);
|
||||||
|
|
||||||
int cov_subscribe_property_decode_service_request(uint8_t * apdu,
|
int cov_subscribe_property_decode_service_request(
|
||||||
unsigned apdu_len, BACNET_SUBSCRIBE_COV_DATA * data);
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
BACNET_SUBSCRIBE_COV_DATA * data);
|
||||||
|
|
||||||
int cov_subscribe_property_encode_adpu(uint8_t * apdu,
|
int cov_subscribe_property_encode_adpu(
|
||||||
uint8_t invoke_id, BACNET_SUBSCRIBE_COV_DATA * data);
|
uint8_t * apdu,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
BACNET_SUBSCRIBE_COV_DATA * data);
|
||||||
|
|
||||||
int cov_subscribe_decode_service_request(uint8_t * apdu,
|
int cov_subscribe_decode_service_request(
|
||||||
unsigned apdu_len, BACNET_SUBSCRIBE_COV_DATA * data);
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
BACNET_SUBSCRIBE_COV_DATA * data);
|
||||||
|
|
||||||
int cov_subscribe_encode_adpu(uint8_t * apdu,
|
int cov_subscribe_encode_adpu(
|
||||||
uint8_t invoke_id, BACNET_SUBSCRIBE_COV_DATA * data);
|
uint8_t * apdu,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
BACNET_SUBSCRIBE_COV_DATA * data);
|
||||||
|
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testCOVNotify(Test * pTest);
|
void testCOVNotify(
|
||||||
void testCOVSubscribeProperty(Test * pTest);
|
Test * pTest);
|
||||||
void testCOVSubscribe(Test * pTest);
|
void testCOVSubscribeProperty(
|
||||||
|
Test * pTest);
|
||||||
|
void testCOVSubscribe(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -40,12 +40,16 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
uint8_t CRC_Calc_Header(uint8_t dataValue, uint8_t crcValue);
|
uint8_t CRC_Calc_Header(
|
||||||
uint16_t CRC_Calc_Data(uint8_t dataValue, uint16_t crcValue);
|
uint8_t dataValue,
|
||||||
|
uint8_t crcValue);
|
||||||
|
uint16_t CRC_Calc_Data(
|
||||||
|
uint8_t dataValue,
|
||||||
|
uint16_t crcValue);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -69,16 +69,16 @@
|
|||||||
#elif defined(BACDL_BIP)
|
#elif defined(BACDL_BIP)
|
||||||
#include "bip.h"
|
#include "bip.h"
|
||||||
#ifdef BBMD_ENABLED
|
#ifdef BBMD_ENABLED
|
||||||
#include "bvlc.h"
|
#include "bvlc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define datalink_init bip_init
|
#define datalink_init bip_init
|
||||||
#ifdef BBMD_ENABLED
|
#ifdef BBMD_ENABLED
|
||||||
#define datalink_send_pdu bvlc_send_pdu
|
#define datalink_send_pdu bvlc_send_pdu
|
||||||
#define datalink_receive bvlc_receive
|
#define datalink_receive bvlc_receive
|
||||||
#else
|
#else
|
||||||
#define datalink_send_pdu bip_send_pdu
|
#define datalink_send_pdu bip_send_pdu
|
||||||
#define datalink_receive bip_receive
|
#define datalink_receive bip_receive
|
||||||
#endif
|
#endif
|
||||||
#define datalink_cleanup bip_cleanup
|
#define datalink_cleanup bip_cleanup
|
||||||
#define datalink_get_broadcast_address bip_get_broadcast_address
|
#define datalink_get_broadcast_address bip_get_broadcast_address
|
||||||
@@ -87,14 +87,24 @@
|
|||||||
#else
|
#else
|
||||||
#include "npdu.h"
|
#include "npdu.h"
|
||||||
|
|
||||||
extern int datalink_send_pdu(BACNET_ADDRESS * dest,
|
extern int datalink_send_pdu(
|
||||||
BACNET_NPDU_DATA * npdu_data, uint8_t * pdu, unsigned pdu_len);
|
BACNET_ADDRESS * dest,
|
||||||
extern uint16_t datalink_receive(BACNET_ADDRESS * src,
|
BACNET_NPDU_DATA * npdu_data,
|
||||||
uint8_t * pdu, uint16_t max_pdu, unsigned timeout);
|
uint8_t * pdu,
|
||||||
extern void datalink_cleanup(void);
|
unsigned pdu_len);
|
||||||
extern void datalink_get_broadcast_address(BACNET_ADDRESS * dest);
|
extern uint16_t datalink_receive(
|
||||||
extern void datalink_get_my_address(BACNET_ADDRESS * my_address);
|
BACNET_ADDRESS * src,
|
||||||
extern void datalink_set_interface(char *ifname);
|
uint8_t * pdu,
|
||||||
|
uint16_t max_pdu,
|
||||||
|
unsigned timeout);
|
||||||
|
extern void datalink_cleanup(
|
||||||
|
void);
|
||||||
|
extern void datalink_get_broadcast_address(
|
||||||
|
BACNET_ADDRESS * dest);
|
||||||
|
extern void datalink_get_my_address(
|
||||||
|
BACNET_ADDRESS * my_address);
|
||||||
|
extern void datalink_set_interface(
|
||||||
|
char *ifname);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -49,10 +49,10 @@ typedef enum BACnet_Weekday {
|
|||||||
|
|
||||||
/* date */
|
/* date */
|
||||||
typedef struct BACnet_Date {
|
typedef struct BACnet_Date {
|
||||||
uint16_t year; /* AD */
|
uint16_t year; /* AD */
|
||||||
uint8_t month; /* 1=Jan */
|
uint8_t month; /* 1=Jan */
|
||||||
uint8_t day; /* 1..31 */
|
uint8_t day; /* 1..31 */
|
||||||
uint8_t wday; /* 1=Monday-7=Sunday */
|
uint8_t wday; /* 1=Monday-7=Sunday */
|
||||||
} BACNET_DATE;
|
} BACNET_DATE;
|
||||||
|
|
||||||
/* time */
|
/* time */
|
||||||
@@ -70,45 +70,75 @@ typedef struct BACnet_DateTime {
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/* utility initialization functions */
|
/* utility initialization functions */
|
||||||
void datetime_set_date(BACNET_DATE * bdate,
|
void datetime_set_date(
|
||||||
uint16_t year, uint8_t month, uint8_t day);
|
BACNET_DATE * bdate,
|
||||||
void datetime_set_time(BACNET_TIME * btime,
|
uint16_t year,
|
||||||
uint8_t hour, uint8_t minute, uint8_t seconds, uint8_t hundredths);
|
uint8_t month,
|
||||||
void datetime_set(BACNET_DATE_TIME * bdatetime,
|
uint8_t day);
|
||||||
BACNET_DATE * bdate, BACNET_TIME * btime);
|
void datetime_set_time(
|
||||||
void datetime_set_values(BACNET_DATE_TIME * bdatetime,
|
BACNET_TIME * btime,
|
||||||
uint16_t year, uint8_t month, uint8_t day,
|
uint8_t hour,
|
||||||
uint8_t hour, uint8_t minute, uint8_t seconds, uint8_t hundredths);
|
uint8_t minute,
|
||||||
|
uint8_t seconds,
|
||||||
|
uint8_t hundredths);
|
||||||
|
void datetime_set(
|
||||||
|
BACNET_DATE_TIME * bdatetime,
|
||||||
|
BACNET_DATE * bdate,
|
||||||
|
BACNET_TIME * btime);
|
||||||
|
void datetime_set_values(
|
||||||
|
BACNET_DATE_TIME * bdatetime,
|
||||||
|
uint16_t year,
|
||||||
|
uint8_t month,
|
||||||
|
uint8_t day,
|
||||||
|
uint8_t hour,
|
||||||
|
uint8_t minute,
|
||||||
|
uint8_t seconds,
|
||||||
|
uint8_t hundredths);
|
||||||
|
|
||||||
/* utility comparison functions:
|
/* utility comparison functions:
|
||||||
if the date/times are the same, return is 0
|
if the date/times are the same, return is 0
|
||||||
if date1 is before date2, returns negative
|
if date1 is before date2, returns negative
|
||||||
if date1 is after date2, returns positive */
|
if date1 is after date2, returns positive */
|
||||||
int datetime_compare_date(BACNET_DATE * date1, BACNET_DATE * date2);
|
int datetime_compare_date(
|
||||||
int datetime_compare_time(BACNET_TIME * time1, BACNET_TIME * time2);
|
BACNET_DATE * date1,
|
||||||
int datetime_compare(BACNET_DATE_TIME * datetime1,
|
BACNET_DATE * date2);
|
||||||
|
int datetime_compare_time(
|
||||||
|
BACNET_TIME * time1,
|
||||||
|
BACNET_TIME * time2);
|
||||||
|
int datetime_compare(
|
||||||
|
BACNET_DATE_TIME * datetime1,
|
||||||
BACNET_DATE_TIME * datetime2);
|
BACNET_DATE_TIME * datetime2);
|
||||||
|
|
||||||
/* utility copy functions */
|
/* utility copy functions */
|
||||||
void datetime_copy_date(BACNET_DATE * date1, BACNET_DATE * date2);
|
void datetime_copy_date(
|
||||||
void datetime_copy_time(BACNET_TIME * time1, BACNET_TIME * time2);
|
BACNET_DATE * date1,
|
||||||
void datetime_copy(BACNET_DATE_TIME * datetime1,
|
BACNET_DATE * date2);
|
||||||
|
void datetime_copy_time(
|
||||||
|
BACNET_TIME * time1,
|
||||||
|
BACNET_TIME * time2);
|
||||||
|
void datetime_copy(
|
||||||
|
BACNET_DATE_TIME * datetime1,
|
||||||
BACNET_DATE_TIME * datetime2);
|
BACNET_DATE_TIME * datetime2);
|
||||||
|
|
||||||
/* utility add function */
|
/* utility add function */
|
||||||
void datetime_add_minutes(BACNET_DATE_TIME * bdatetime,
|
void datetime_add_minutes(
|
||||||
|
BACNET_DATE_TIME * bdatetime,
|
||||||
uint32_t minutes);
|
uint32_t minutes);
|
||||||
|
|
||||||
/* date and time wildcards */
|
/* date and time wildcards */
|
||||||
bool datetime_wildcard(BACNET_DATE_TIME * bdatetime);
|
bool datetime_wildcard(
|
||||||
void datetime_wildcard_set(BACNET_DATE_TIME * bdatetime);
|
BACNET_DATE_TIME * bdatetime);
|
||||||
void datetime_date_wildcard_set(BACNET_DATE * bdate);
|
void datetime_wildcard_set(
|
||||||
void datetime_time_wildcard_set(BACNET_TIME * btime);
|
BACNET_DATE_TIME * bdatetime);
|
||||||
|
void datetime_date_wildcard_set(
|
||||||
|
BACNET_DATE * bdate);
|
||||||
|
void datetime_time_wildcard_set(
|
||||||
|
BACNET_TIME * btime);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif /* DATE_TIME_H */
|
#endif /* DATE_TIME_H */
|
||||||
|
|||||||
+29
-15
@@ -41,28 +41,40 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/* return the status */
|
/* return the status */
|
||||||
BACNET_COMMUNICATION_ENABLE_DISABLE dcc_enable_status(void);
|
BACNET_COMMUNICATION_ENABLE_DISABLE dcc_enable_status(
|
||||||
bool dcc_communication_enabled(void);
|
void);
|
||||||
bool dcc_communication_disabled(void);
|
bool dcc_communication_enabled(
|
||||||
bool dcc_communication_initiation_disabled(void);
|
void);
|
||||||
|
bool dcc_communication_disabled(
|
||||||
|
void);
|
||||||
|
bool dcc_communication_initiation_disabled(
|
||||||
|
void);
|
||||||
/* return the time */
|
/* return the time */
|
||||||
uint32_t dcc_duration_seconds(void);
|
uint32_t dcc_duration_seconds(
|
||||||
|
void);
|
||||||
/* called every second or so. If more than one second,
|
/* called every second or so. If more than one second,
|
||||||
then seconds should be the number of seconds to tick away */
|
then seconds should be the number of seconds to tick away */
|
||||||
void dcc_timer_seconds(uint32_t seconds);
|
void dcc_timer_seconds(
|
||||||
|
uint32_t seconds);
|
||||||
/* setup the communication values */
|
/* setup the communication values */
|
||||||
bool dcc_set_status_duration(BACNET_COMMUNICATION_ENABLE_DISABLE
|
bool dcc_set_status_duration(
|
||||||
status, uint16_t minutes);
|
BACNET_COMMUNICATION_ENABLE_DISABLE status,
|
||||||
|
uint16_t minutes);
|
||||||
|
|
||||||
/* encode service */
|
/* encode service */
|
||||||
int dcc_encode_apdu(uint8_t * apdu, uint8_t invoke_id, uint16_t timeDuration, /* 0=optional */
|
int dcc_encode_apdu(
|
||||||
BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable, BACNET_CHARACTER_STRING * password); /* NULL=optional */
|
uint8_t * apdu,
|
||||||
|
uint8_t invoke_id,
|
||||||
|
uint16_t timeDuration, /* 0=optional */
|
||||||
|
BACNET_COMMUNICATION_ENABLE_DISABLE enable_disable,
|
||||||
|
BACNET_CHARACTER_STRING * password); /* NULL=optional */
|
||||||
|
|
||||||
/* decode the service request only */
|
/* decode the service request only */
|
||||||
int dcc_decode_service_request(uint8_t * apdu,
|
int dcc_decode_service_request(
|
||||||
|
uint8_t * apdu,
|
||||||
unsigned apdu_len,
|
unsigned apdu_len,
|
||||||
uint16_t * timeDuration,
|
uint16_t * timeDuration,
|
||||||
BACNET_COMMUNICATION_ENABLE_DISABLE * enable_disable,
|
BACNET_COMMUNICATION_ENABLE_DISABLE * enable_disable,
|
||||||
@@ -70,17 +82,19 @@ extern "C" {
|
|||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
int dcc_decode_apdu(uint8_t * apdu,
|
int dcc_decode_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
unsigned apdu_len,
|
unsigned apdu_len,
|
||||||
uint8_t * invoke_id,
|
uint8_t * invoke_id,
|
||||||
uint16_t * timeDuration,
|
uint16_t * timeDuration,
|
||||||
BACNET_COMMUNICATION_ENABLE_DISABLE * enable_disable,
|
BACNET_COMMUNICATION_ENABLE_DISABLE * enable_disable,
|
||||||
BACNET_CHARACTER_STRING * password);
|
BACNET_CHARACTER_STRING * password);
|
||||||
|
|
||||||
void test_DeviceCommunicationControl(Test * pTest);
|
void test_DeviceCommunicationControl(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -42,71 +42,110 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void Device_Property_Lists(
|
void Device_Property_Lists(
|
||||||
const int **pRequired,
|
const int **pRequired,
|
||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary);
|
const int **pProprietary);
|
||||||
|
|
||||||
uint32_t Device_Object_Instance_Number(void);
|
uint32_t Device_Object_Instance_Number(
|
||||||
bool Device_Set_Object_Instance_Number(uint32_t object_id);
|
void);
|
||||||
bool Device_Valid_Object_Instance_Number(uint32_t object_id);
|
bool Device_Set_Object_Instance_Number(
|
||||||
unsigned Device_Object_List_Count(void);
|
uint32_t object_id);
|
||||||
bool Device_Object_List_Identifier(unsigned array_index,
|
bool Device_Valid_Object_Instance_Number(
|
||||||
int *object_type, uint32_t * instance);
|
uint32_t object_id);
|
||||||
|
unsigned Device_Object_List_Count(
|
||||||
|
void);
|
||||||
|
bool Device_Object_List_Identifier(
|
||||||
|
unsigned array_index,
|
||||||
|
int *object_type,
|
||||||
|
uint32_t * instance);
|
||||||
|
|
||||||
BACNET_DEVICE_STATUS Device_System_Status(void);
|
BACNET_DEVICE_STATUS Device_System_Status(
|
||||||
void Device_Set_System_Status(BACNET_DEVICE_STATUS status);
|
void);
|
||||||
|
void Device_Set_System_Status(
|
||||||
|
BACNET_DEVICE_STATUS status);
|
||||||
|
|
||||||
const char *Device_Vendor_Name(void);
|
const char *Device_Vendor_Name(
|
||||||
|
void);
|
||||||
|
|
||||||
uint16_t Device_Vendor_Identifier(void);
|
uint16_t Device_Vendor_Identifier(
|
||||||
|
void);
|
||||||
|
|
||||||
const char *Device_Model_Name(void);
|
const char *Device_Model_Name(
|
||||||
bool Device_Set_Model_Name(const char *name, size_t length);
|
void);
|
||||||
|
bool Device_Set_Model_Name(
|
||||||
const char *Device_Firmware_Revision(void);
|
const char *name,
|
||||||
|
|
||||||
const char *Device_Application_Software_Version(void);
|
|
||||||
bool Device_Set_Application_Software_Version(const char *name,
|
|
||||||
size_t length);
|
size_t length);
|
||||||
|
|
||||||
const char *Device_Description(void);
|
const char *Device_Firmware_Revision(
|
||||||
bool Device_Set_Description(const char *name, size_t length);
|
void);
|
||||||
|
|
||||||
const char *Device_Location(void);
|
const char *Device_Application_Software_Version(
|
||||||
bool Device_Set_Location(const char *name, size_t length);
|
void);
|
||||||
|
bool Device_Set_Application_Software_Version(
|
||||||
|
const char *name,
|
||||||
|
size_t length);
|
||||||
|
|
||||||
|
const char *Device_Description(
|
||||||
|
void);
|
||||||
|
bool Device_Set_Description(
|
||||||
|
const char *name,
|
||||||
|
size_t length);
|
||||||
|
|
||||||
|
const char *Device_Location(
|
||||||
|
void);
|
||||||
|
bool Device_Set_Location(
|
||||||
|
const char *name,
|
||||||
|
size_t length);
|
||||||
|
|
||||||
/* some stack-centric constant values - no set methods */
|
/* some stack-centric constant values - no set methods */
|
||||||
uint8_t Device_Protocol_Version(void);
|
uint8_t Device_Protocol_Version(
|
||||||
uint8_t Device_Protocol_Revision(void);
|
void);
|
||||||
uint16_t Device_Max_APDU_Length_Accepted(void);
|
uint8_t Device_Protocol_Revision(
|
||||||
BACNET_SEGMENTATION Device_Segmentation_Supported(void);
|
void);
|
||||||
|
uint16_t Device_Max_APDU_Length_Accepted(
|
||||||
|
void);
|
||||||
|
BACNET_SEGMENTATION Device_Segmentation_Supported(
|
||||||
|
void);
|
||||||
|
|
||||||
uint16_t Device_APDU_Timeout(void);
|
uint16_t Device_APDU_Timeout(
|
||||||
void Device_Set_APDU_Timeout(uint16_t timeout);
|
void);
|
||||||
|
void Device_Set_APDU_Timeout(
|
||||||
|
uint16_t timeout);
|
||||||
|
|
||||||
uint8_t Device_Number_Of_APDU_Retries(void);
|
uint8_t Device_Number_Of_APDU_Retries(
|
||||||
void Device_Set_Number_Of_APDU_Retries(uint8_t retries);
|
void);
|
||||||
|
void Device_Set_Number_Of_APDU_Retries(
|
||||||
|
uint8_t retries);
|
||||||
|
|
||||||
uint8_t Device_Database_Revision(void);
|
uint8_t Device_Database_Revision(
|
||||||
void Device_Set_Database_Revision(uint8_t revision);
|
void);
|
||||||
|
void Device_Set_Database_Revision(
|
||||||
|
uint8_t revision);
|
||||||
|
|
||||||
bool Device_Valid_Object_Name(const char *object_name,
|
bool Device_Valid_Object_Name(
|
||||||
int *object_type, uint32_t * object_instance);
|
const char *object_name,
|
||||||
char *Device_Valid_Object_Id(int object_type,
|
int *object_type,
|
||||||
|
uint32_t * object_instance);
|
||||||
|
char *Device_Valid_Object_Id(
|
||||||
|
int object_type,
|
||||||
uint32_t object_instance);
|
uint32_t object_instance);
|
||||||
|
|
||||||
int Device_Encode_Property_APDU(uint8_t * apdu,
|
int Device_Encode_Property_APDU(
|
||||||
|
uint8_t * apdu,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
int32_t array_index,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Device_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -46,29 +46,33 @@
|
|||||||
#define MAX_MPDU (MAX_HEADER+MAX_PDU)
|
#define MAX_MPDU (MAX_HEADER+MAX_PDU)
|
||||||
|
|
||||||
typedef struct dlmstp_packet {
|
typedef struct dlmstp_packet {
|
||||||
bool ready; /* true if ready to be sent or received */
|
bool ready; /* true if ready to be sent or received */
|
||||||
BACNET_ADDRESS address; /* source address */
|
BACNET_ADDRESS address; /* source address */
|
||||||
uint8_t frame_type; /* type of message */
|
uint8_t frame_type; /* type of message */
|
||||||
uint16_t pdu_len; /* packet length */
|
uint16_t pdu_len; /* packet length */
|
||||||
uint8_t pdu[MAX_MPDU]; /* packet */
|
uint8_t pdu[MAX_MPDU]; /* packet */
|
||||||
} DLMSTP_PACKET;
|
} DLMSTP_PACKET;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
bool dlmstp_init(char *ifname);
|
bool dlmstp_init(
|
||||||
void dlmstp_cleanup(void);
|
char *ifname);
|
||||||
|
void dlmstp_cleanup(
|
||||||
|
void);
|
||||||
|
|
||||||
/* returns number of bytes sent on success, negative on failure */
|
/* returns number of bytes sent on success, negative on failure */
|
||||||
int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
int dlmstp_send_pdu(
|
||||||
|
BACNET_ADDRESS * dest, /* destination address */
|
||||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||||
uint8_t * pdu, /* any data to be sent - may be null */
|
uint8_t * pdu, /* any data to be sent - may be null */
|
||||||
unsigned pdu_len); /* number of bytes of data */
|
unsigned pdu_len); /* number of bytes of data */
|
||||||
|
|
||||||
/* returns the number of octets in the PDU, or zero on failure */
|
/* returns the number of octets in the PDU, or zero on failure */
|
||||||
uint16_t dlmstp_receive(BACNET_ADDRESS * src, /* source address */
|
uint16_t dlmstp_receive(
|
||||||
uint8_t * pdu, /* PDU data */
|
BACNET_ADDRESS * src, /* source address */
|
||||||
|
uint8_t * pdu, /* PDU data */
|
||||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||||
unsigned timeout); /* milliseconds to wait for a packet */
|
unsigned timeout); /* milliseconds to wait for a packet */
|
||||||
|
|
||||||
@@ -79,29 +83,39 @@ extern "C" {
|
|||||||
/* nodes. This may be used to allocate more or less of the available link */
|
/* nodes. This may be used to allocate more or less of the available link */
|
||||||
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
|
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
|
||||||
/* node, its value shall be 1. */
|
/* node, its value shall be 1. */
|
||||||
void dlmstp_set_max_info_frames(uint8_t max_info_frames);
|
void dlmstp_set_max_info_frames(
|
||||||
uint8_t dlmstp_max_info_frames(void);
|
uint8_t max_info_frames);
|
||||||
|
uint8_t dlmstp_max_info_frames(
|
||||||
|
void);
|
||||||
|
|
||||||
/* This parameter represents the value of the Max_Master property of the */
|
/* This parameter represents the value of the Max_Master property of the */
|
||||||
/* node's Device object. The value of Max_Master specifies the highest */
|
/* node's Device object. The value of Max_Master specifies the highest */
|
||||||
/* allowable address for master nodes. The value of Max_Master shall be */
|
/* allowable address for master nodes. The value of Max_Master shall be */
|
||||||
/* less than or equal to 127. If Max_Master is not writable in a node, */
|
/* less than or equal to 127. If Max_Master is not writable in a node, */
|
||||||
/* its value shall be 127. */
|
/* its value shall be 127. */
|
||||||
void dlmstp_set_max_master(uint8_t max_master);
|
void dlmstp_set_max_master(
|
||||||
uint8_t dlmstp_max_master(void);
|
uint8_t max_master);
|
||||||
|
uint8_t dlmstp_max_master(
|
||||||
|
void);
|
||||||
|
|
||||||
/* MAC address 0-127 */
|
/* MAC address 0-127 */
|
||||||
void dlmstp_set_mac_address(uint8_t my_address);
|
void dlmstp_set_mac_address(
|
||||||
uint8_t dlmstp_mac_address(void);
|
uint8_t my_address);
|
||||||
|
uint8_t dlmstp_mac_address(
|
||||||
|
void);
|
||||||
|
|
||||||
void dlmstp_get_my_address(BACNET_ADDRESS * my_address);
|
void dlmstp_get_my_address(
|
||||||
void dlmstp_get_broadcast_address(BACNET_ADDRESS * dest); /* destination address */
|
BACNET_ADDRESS * my_address);
|
||||||
|
void dlmstp_get_broadcast_address(
|
||||||
|
BACNET_ADDRESS * dest); /* destination address */
|
||||||
|
|
||||||
/* RS485 Baud Rate 9600, 19200, 38400, 57600, 115200 */
|
/* RS485 Baud Rate 9600, 19200, 38400, 57600, 115200 */
|
||||||
void dlmstp_set_baud_rate(uint32_t baud);
|
void dlmstp_set_baud_rate(
|
||||||
uint32_t dlmstp_baud_rate(void);
|
uint32_t baud);
|
||||||
|
uint32_t dlmstp_baud_rate(
|
||||||
|
void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -46,31 +46,39 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
bool ethernet_valid(void);
|
bool ethernet_valid(
|
||||||
void ethernet_cleanup(void);
|
void);
|
||||||
bool ethernet_init(char *interface_name);
|
void ethernet_cleanup(
|
||||||
|
void);
|
||||||
|
bool ethernet_init(
|
||||||
|
char *interface_name);
|
||||||
|
|
||||||
/* function to send a packet out the 802.2 socket */
|
/* function to send a packet out the 802.2 socket */
|
||||||
/* returns number of bytes sent on success, negative on failure */
|
/* returns number of bytes sent on success, negative on failure */
|
||||||
int ethernet_send_pdu(BACNET_ADDRESS * dest, /* destination address */
|
int ethernet_send_pdu(
|
||||||
|
BACNET_ADDRESS * dest, /* destination address */
|
||||||
BACNET_NPDU_DATA * npdu_data, /* network information */
|
BACNET_NPDU_DATA * npdu_data, /* network information */
|
||||||
uint8_t * pdu, /* any data to be sent - may be null */
|
uint8_t * pdu, /* any data to be sent - may be null */
|
||||||
unsigned pdu_len); /* number of bytes of data */
|
unsigned pdu_len); /* number of bytes of data */
|
||||||
|
|
||||||
/* receives an 802.2 framed packet */
|
/* receives an 802.2 framed packet */
|
||||||
/* returns the number of octets in the PDU, or zero on failure */
|
/* returns the number of octets in the PDU, or zero on failure */
|
||||||
uint16_t ethernet_receive(BACNET_ADDRESS * src, /* source address */
|
uint16_t ethernet_receive(
|
||||||
uint8_t * pdu, /* PDU data */
|
BACNET_ADDRESS * src, /* source address */
|
||||||
|
uint8_t * pdu, /* PDU data */
|
||||||
uint16_t max_pdu, /* amount of space available in the PDU */
|
uint16_t max_pdu, /* amount of space available in the PDU */
|
||||||
unsigned timeout); /* milliseconds to wait for a packet */
|
unsigned timeout); /* milliseconds to wait for a packet */
|
||||||
|
|
||||||
void ethernet_set_my_address(BACNET_ADDRESS * my_address);
|
void ethernet_set_my_address(
|
||||||
void ethernet_get_my_address(BACNET_ADDRESS * my_address);
|
BACNET_ADDRESS * my_address);
|
||||||
void ethernet_get_broadcast_address(BACNET_ADDRESS * dest); /* destination address */
|
void ethernet_get_my_address(
|
||||||
|
BACNET_ADDRESS * my_address);
|
||||||
|
void ethernet_get_broadcast_address(
|
||||||
|
BACNET_ADDRESS * dest); /* destination address */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -36,11 +36,12 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
char *filename_remove_path(const char *filename_in);
|
char *filename_remove_path(
|
||||||
|
const char *filename_in);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -34,72 +34,96 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void handler_unrecognized_service(uint8_t * service_request,
|
void handler_unrecognized_service(
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
uint16_t service_len,
|
||||||
BACNET_ADDRESS * dest,
|
BACNET_ADDRESS * dest,
|
||||||
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||||
|
|
||||||
void handler_who_is(uint8_t * service_request,
|
void handler_who_is(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src);
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
void handler_who_has(uint8_t * service_request,
|
void handler_who_has(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src);
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
void handler_i_am_add(uint8_t * service_request,
|
void handler_i_am_add(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src);
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
void handler_i_am_bind(uint8_t * service_request,
|
void handler_i_am_bind(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src);
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
void handler_read_property(uint8_t * service_request,
|
void handler_read_property(
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
uint16_t service_len,
|
||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||||
|
|
||||||
void handler_read_property_ack(uint8_t * service_request,
|
void handler_read_property_ack(
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
uint16_t service_len,
|
||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
|
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
|
||||||
|
|
||||||
void handler_write_property(uint8_t * service_request,
|
void handler_write_property(
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
uint16_t service_len,
|
||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||||
|
|
||||||
void handler_atomic_read_file(uint8_t * service_request,
|
void handler_atomic_read_file(
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
uint16_t service_len,
|
||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||||
|
|
||||||
void handler_atomic_read_file_ack(uint8_t * service_request,
|
void handler_atomic_read_file_ack(
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
uint16_t service_len,
|
||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
|
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
|
||||||
|
|
||||||
void handler_atomic_write_file(uint8_t * service_request,
|
void handler_atomic_write_file(
|
||||||
uint16_t service_len,
|
uint8_t * service_request,
|
||||||
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
|
||||||
|
|
||||||
void handler_reinitialize_device(uint8_t * service_request,
|
|
||||||
uint16_t service_len,
|
uint16_t service_len,
|
||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||||
|
|
||||||
void handler_device_communication_control(uint8_t * service_request,
|
void handler_reinitialize_device(
|
||||||
|
uint8_t * service_request,
|
||||||
uint16_t service_len,
|
uint16_t service_len,
|
||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||||
|
|
||||||
void handler_i_have(uint8_t * service_request,
|
void handler_device_communication_control(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src);
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src,
|
||||||
|
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||||
|
|
||||||
void handler_timesync(uint8_t * service_request,
|
void handler_i_have(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src);
|
uint8_t * service_request,
|
||||||
|
uint16_t service_len,
|
||||||
|
BACNET_ADDRESS * src);
|
||||||
|
|
||||||
void handler_timesync_utc(uint8_t * service_request,
|
void handler_timesync(
|
||||||
uint16_t service_len, BACNET_ADDRESS * src);
|
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);
|
||||||
|
|
||||||
void handler_read_property_multiple(
|
void handler_read_property_multiple(
|
||||||
uint8_t * service_request,
|
uint8_t * service_request,
|
||||||
@@ -108,7 +132,7 @@ extern "C" {
|
|||||||
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||||
|
|
||||||
/* Encodes the property APDU and returns the length,
|
/* Encodes the property APDU and returns the length,
|
||||||
or sets the error, and returns -1 */
|
or sets the error, and returns -1 */
|
||||||
/* resides in h_rp.c */
|
/* resides in h_rp.c */
|
||||||
int Encode_Property_APDU(
|
int Encode_Property_APDU(
|
||||||
uint8_t * apdu,
|
uint8_t * apdu,
|
||||||
@@ -123,5 +147,5 @@ extern "C" {
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+25
-14
@@ -42,33 +42,44 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
int iam_encode_apdu(uint8_t * apdu,
|
int iam_encode_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t device_id,
|
uint32_t device_id,
|
||||||
unsigned max_apdu, int segmentation, uint16_t vendor_id);
|
unsigned max_apdu,
|
||||||
|
int segmentation,
|
||||||
|
uint16_t vendor_id);
|
||||||
|
|
||||||
int iam_decode_service_request(uint8_t * apdu,
|
int iam_decode_service_request(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t * pDevice_id,
|
uint32_t * pDevice_id,
|
||||||
unsigned *pMax_apdu, int *pSegmentation, uint16_t * pVendor_id);
|
unsigned *pMax_apdu,
|
||||||
|
int *pSegmentation,
|
||||||
|
uint16_t * pVendor_id);
|
||||||
|
|
||||||
int iam_encode_pdu(
|
int iam_encode_pdu(
|
||||||
uint8_t * buffer,
|
uint8_t * buffer,
|
||||||
BACNET_ADDRESS *dest,
|
BACNET_ADDRESS * dest,
|
||||||
BACNET_NPDU_DATA *npdu_data);
|
BACNET_NPDU_DATA * npdu_data);
|
||||||
|
|
||||||
int iam_send(uint8_t * buffer);
|
int iam_send(
|
||||||
|
uint8_t * buffer);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
int iam_decode_apdu(uint8_t * apdu,
|
int iam_decode_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t * pDevice_id,
|
uint32_t * pDevice_id,
|
||||||
unsigned *pMax_apdu, int *pSegmentation, uint16_t * pVendor_id);
|
unsigned *pMax_apdu,
|
||||||
|
int *pSegmentation,
|
||||||
|
uint16_t * pVendor_id);
|
||||||
|
|
||||||
void testIAm(Test * pTest);
|
void testIAm(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -46,22 +46,29 @@ typedef struct BACnet_I_Have_Data {
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
int ihave_encode_apdu(uint8_t * apdu, BACNET_I_HAVE_DATA * data);
|
int ihave_encode_apdu(
|
||||||
|
uint8_t * apdu,
|
||||||
|
BACNET_I_HAVE_DATA * data);
|
||||||
|
|
||||||
int ihave_decode_service_request(uint8_t * apdu,
|
int ihave_decode_service_request(
|
||||||
unsigned apdu_len, BACNET_I_HAVE_DATA * data);
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
BACNET_I_HAVE_DATA * data);
|
||||||
|
|
||||||
int ihave_decode_apdu(uint8_t * apdu,
|
int ihave_decode_apdu(
|
||||||
unsigned apdu_len, BACNET_I_HAVE_DATA * data);
|
uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
BACNET_I_HAVE_DATA * data);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testIHave(Test * pTest);
|
void testIHave(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -40,56 +40,72 @@
|
|||||||
|
|
||||||
/* index and text pairs */
|
/* index and text pairs */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned index; /* index number that matches the text */
|
unsigned index; /* index number that matches the text */
|
||||||
const char *pString; /* text pair - use NULL to end the list */
|
const char *pString; /* text pair - use NULL to end the list */
|
||||||
} INDTEXT_DATA;
|
} INDTEXT_DATA;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/* Searches for a matching string and returns the index to the string
|
/* Searches for a matching string and returns the index to the string
|
||||||
in the parameter found_index.
|
in the parameter found_index.
|
||||||
If the string is not found, false is returned
|
If the string is not found, false is returned
|
||||||
If the string is found, true is returned and the found_index contains
|
If the string is found, true is returned and the found_index contains
|
||||||
the first index where the string was found. */
|
the first index where the string was found. */
|
||||||
bool indtext_by_string(INDTEXT_DATA * data_list,
|
bool indtext_by_string(
|
||||||
const char *search_name, unsigned *found_index);
|
INDTEXT_DATA * data_list,
|
||||||
|
const char *search_name,
|
||||||
|
unsigned *found_index);
|
||||||
/* case insensitive version */
|
/* case insensitive version */
|
||||||
bool indtext_by_istring(INDTEXT_DATA * data_list,
|
bool indtext_by_istring(
|
||||||
const char *search_name, unsigned *found_index);
|
INDTEXT_DATA * data_list,
|
||||||
|
const char *search_name,
|
||||||
|
unsigned *found_index);
|
||||||
/* Searches for a matching string and returns the index to the string
|
/* Searches for a matching string and returns the index to the string
|
||||||
or the default_index if the string is not found. */
|
or the default_index if the string is not found. */
|
||||||
unsigned indtext_by_string_default(INDTEXT_DATA * data_list,
|
unsigned indtext_by_string_default(
|
||||||
const char *search_name, unsigned default_index);
|
INDTEXT_DATA * data_list,
|
||||||
|
const char *search_name,
|
||||||
|
unsigned default_index);
|
||||||
/* case insensitive version */
|
/* case insensitive version */
|
||||||
unsigned indtext_by_istring_default(INDTEXT_DATA * data_list,
|
unsigned indtext_by_istring_default(
|
||||||
const char *search_name, unsigned default_index);
|
INDTEXT_DATA * data_list,
|
||||||
|
const char *search_name,
|
||||||
|
unsigned default_index);
|
||||||
/* for a given index, return the matching string,
|
/* for a given index, return the matching string,
|
||||||
or NULL if not found */
|
or NULL if not found */
|
||||||
const char *indtext_by_index(INDTEXT_DATA * data_list, unsigned index);
|
const char *indtext_by_index(
|
||||||
|
INDTEXT_DATA * data_list,
|
||||||
|
unsigned index);
|
||||||
/* for a given index, return the matching string,
|
/* for a given index, return the matching string,
|
||||||
or default_name if not found */
|
or default_name if not found */
|
||||||
const char *indtext_by_index_default(INDTEXT_DATA * data_list,
|
const char *indtext_by_index_default(
|
||||||
unsigned index, const char *default_name);
|
INDTEXT_DATA * data_list,
|
||||||
|
unsigned index,
|
||||||
|
const char *default_name);
|
||||||
/* for a given index, return the matching string,
|
/* for a given index, return the matching string,
|
||||||
or default_name if not found.
|
or default_name if not found.
|
||||||
if the index is before the split,
|
if the index is before the split,
|
||||||
the before_split_default_name is used */
|
the before_split_default_name is used */
|
||||||
const char *indtext_by_index_split_default(INDTEXT_DATA * data_list,
|
const char *indtext_by_index_split_default(
|
||||||
|
INDTEXT_DATA * data_list,
|
||||||
int index,
|
int index,
|
||||||
int split_index,
|
int split_index,
|
||||||
const char *before_split_default_name, const char *default_name);
|
const char *before_split_default_name,
|
||||||
|
const char *default_name);
|
||||||
|
|
||||||
/* returns the number of elements in the list */
|
/* returns the number of elements in the list */
|
||||||
unsigned indtext_count(INDTEXT_DATA * data_list);
|
unsigned indtext_count(
|
||||||
|
INDTEXT_DATA * data_list);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testIndexText(Test * pTest);
|
void testIndexText(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -42,52 +42,71 @@
|
|||||||
|
|
||||||
/* list data and datatype */
|
/* list data and datatype */
|
||||||
struct Keylist_Node {
|
struct Keylist_Node {
|
||||||
KEY key; /* unique number that is sorted in the list */
|
KEY key; /* unique number that is sorted in the list */
|
||||||
void *data; /* pointer to some data that is stored */
|
void *data; /* pointer to some data that is stored */
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Keylist {
|
typedef struct Keylist {
|
||||||
struct Keylist_Node **array; /* array of nodes */
|
struct Keylist_Node **array; /* array of nodes */
|
||||||
int count; /* number of nodes in this list - more effecient than loop */
|
int count; /* number of nodes in this list - more effecient than loop */
|
||||||
int size; /* number of available nodes on this list - can grow or shrink */
|
int size; /* number of available nodes on this list - can grow or shrink */
|
||||||
} KEYLIST_TYPE;
|
} KEYLIST_TYPE;
|
||||||
typedef KEYLIST_TYPE *OS_Keylist;
|
typedef KEYLIST_TYPE *OS_Keylist;
|
||||||
|
|
||||||
/* returns head of the list or NULL on failure. */
|
/* returns head of the list or NULL on failure. */
|
||||||
OS_Keylist Keylist_Create(void);
|
OS_Keylist Keylist_Create(
|
||||||
|
void);
|
||||||
|
|
||||||
/* delete specified list */
|
/* delete specified list */
|
||||||
/* note: you should pop all the nodes off the list first. */
|
/* note: you should pop all the nodes off the list first. */
|
||||||
void Keylist_Delete(OS_Keylist list);
|
void Keylist_Delete(
|
||||||
|
OS_Keylist list);
|
||||||
|
|
||||||
/* inserts a node into its sorted position */
|
/* inserts a node into its sorted position */
|
||||||
/* returns the index where it was added */
|
/* returns the index where it was added */
|
||||||
int Keylist_Data_Add(OS_Keylist list, KEY key, void *data);
|
int Keylist_Data_Add(
|
||||||
|
OS_Keylist list,
|
||||||
|
KEY key,
|
||||||
|
void *data);
|
||||||
|
|
||||||
/* deletes a node specified by its key */
|
/* deletes a node specified by its key */
|
||||||
/* returns the data from the node */
|
/* returns the data from the node */
|
||||||
void *Keylist_Data_Delete(OS_Keylist list, KEY key);
|
void *Keylist_Data_Delete(
|
||||||
|
OS_Keylist list,
|
||||||
|
KEY key);
|
||||||
|
|
||||||
/* deletes a node specified by its index */
|
/* deletes a node specified by its index */
|
||||||
/* returns the data from the node */
|
/* returns the data from the node */
|
||||||
void *Keylist_Data_Delete_By_Index(OS_Keylist list, int index);
|
void *Keylist_Data_Delete_By_Index(
|
||||||
|
OS_Keylist list,
|
||||||
|
int index);
|
||||||
|
|
||||||
/* returns the data from last node, and removes it from the list */
|
/* returns the data from last node, and removes it from the list */
|
||||||
void *Keylist_Data_Pop(OS_Keylist list);
|
void *Keylist_Data_Pop(
|
||||||
|
OS_Keylist list);
|
||||||
|
|
||||||
/* returns the data from the node specified by key */
|
/* returns the data from the node specified by key */
|
||||||
void *Keylist_Data(OS_Keylist list, KEY key);
|
void *Keylist_Data(
|
||||||
|
OS_Keylist list,
|
||||||
|
KEY key);
|
||||||
|
|
||||||
/* returns the data specified by key */
|
/* returns the data specified by key */
|
||||||
void *Keylist_Data_Index(OS_Keylist list, int index);
|
void *Keylist_Data_Index(
|
||||||
|
OS_Keylist list,
|
||||||
|
int index);
|
||||||
|
|
||||||
/* return the key at the given index */
|
/* return the key at the given index */
|
||||||
KEY Keylist_Key(OS_Keylist list, int index);
|
KEY Keylist_Key(
|
||||||
|
OS_Keylist list,
|
||||||
|
int index);
|
||||||
|
|
||||||
/* returns the next empty key from the list */
|
/* returns the next empty key from the list */
|
||||||
KEY Keylist_Next_Empty_Key(OS_Keylist list, KEY key);
|
KEY Keylist_Next_Empty_Key(
|
||||||
|
OS_Keylist list,
|
||||||
|
KEY key);
|
||||||
|
|
||||||
/* returns the number of items in the list */
|
/* returns the number of items in the list */
|
||||||
int Keylist_Count(OS_Keylist list);
|
int Keylist_Count(
|
||||||
|
OS_Keylist list);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+22
-12
@@ -33,34 +33,44 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void Load_Control_Property_Lists(
|
void Load_Control_Property_Lists(
|
||||||
const int **pRequired,
|
const int **pRequired,
|
||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary);
|
const int **pProprietary);
|
||||||
void Load_Control_State_Machine_Handler(void);
|
void Load_Control_State_Machine_Handler(
|
||||||
|
void);
|
||||||
|
|
||||||
bool Load_Control_Valid_Instance(uint32_t object_instance);
|
bool Load_Control_Valid_Instance(
|
||||||
unsigned Load_Control_Count(void);
|
uint32_t object_instance);
|
||||||
uint32_t Load_Control_Index_To_Instance(unsigned index);
|
unsigned Load_Control_Count(
|
||||||
char *Load_Control_Name(uint32_t object_instance);
|
void);
|
||||||
|
uint32_t Load_Control_Index_To_Instance(
|
||||||
|
unsigned index);
|
||||||
|
char *Load_Control_Name(
|
||||||
|
uint32_t object_instance);
|
||||||
|
|
||||||
int Load_Control_Encode_Property_APDU(uint8_t * apdu,
|
int Load_Control_Encode_Property_APDU(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
int32_t array_index,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
bool Load_Control_Write_Property(
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testLoadControl(Test * pTest);
|
void testLoadControl(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+32
-19
@@ -33,37 +33,50 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
bool Analog_Output_Valid_Instance(uint32_t object_instance);
|
bool Analog_Output_Valid_Instance(
|
||||||
unsigned Lighting_Output_Count(void);
|
uint32_t object_instance);
|
||||||
uint32_t Lighting_Output_Index_To_Instance(unsigned index);
|
unsigned Lighting_Output_Count(
|
||||||
char *Lighting_Output_Name(uint32_t object_instance);
|
void);
|
||||||
float Lighting_Output_Present_Value(uint32_t object_instance);
|
uint32_t Lighting_Output_Index_To_Instance(
|
||||||
unsigned Lighting_Output_Present_Value_Priority(uint32_t
|
unsigned index);
|
||||||
object_instance);
|
char *Lighting_Output_Name(
|
||||||
bool Lighting_Output_Present_Value_Set(uint32_t object_instance,
|
uint32_t object_instance);
|
||||||
float value, unsigned priority);
|
float Lighting_Output_Present_Value(
|
||||||
bool Lighting_Output_Present_Value_Relinquish(uint32_t object_instance,
|
uint32_t object_instance);
|
||||||
|
unsigned Lighting_Output_Present_Value_Priority(
|
||||||
|
uint32_t object_instance);
|
||||||
|
bool Lighting_Output_Present_Value_Set(
|
||||||
|
uint32_t object_instance,
|
||||||
|
float value,
|
||||||
|
unsigned priority);
|
||||||
|
bool Lighting_Output_Present_Value_Relinquish(
|
||||||
|
uint32_t object_instance,
|
||||||
int priority);
|
int priority);
|
||||||
|
|
||||||
|
|
||||||
/* ReadProperty service support */
|
/* ReadProperty service support */
|
||||||
int Lighting_Output_Encode_Property_APDU(uint8_t * apdu,
|
int Lighting_Output_Encode_Property_APDU(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
int32_t array_index,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
/* WriteProperty service support */
|
BACNET_ERROR_CODE * error_code);
|
||||||
bool Lighting_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
|
/* WriteProperty service support */
|
||||||
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);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testLightingOutput(Test * pTest);
|
void testLightingOutput(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+19
-11
@@ -33,33 +33,41 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void Life_Safety_Point_Property_Lists(
|
void Life_Safety_Point_Property_Lists(
|
||||||
const int **pRequired,
|
const int **pRequired,
|
||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary);
|
const int **pProprietary);
|
||||||
bool Life_Safety_Point_Valid_Instance(uint32_t object_instance);
|
bool Life_Safety_Point_Valid_Instance(
|
||||||
unsigned Life_Safety_Point_Count(void);
|
uint32_t object_instance);
|
||||||
uint32_t Life_Safety_Point_Index_To_Instance(unsigned index);
|
unsigned Life_Safety_Point_Count(
|
||||||
char *Life_Safety_Point_Name(uint32_t object_instance);
|
void);
|
||||||
|
uint32_t Life_Safety_Point_Index_To_Instance(
|
||||||
|
unsigned index);
|
||||||
|
char *Life_Safety_Point_Name(
|
||||||
|
uint32_t object_instance);
|
||||||
|
|
||||||
int Life_Safety_Point_Encode_Property_APDU(uint8_t * apdu,
|
int Life_Safety_Point_Encode_Property_APDU(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
int32_t array_index,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
bool Life_Safety_Point_Write_Property(BACNET_WRITE_PROPERTY_DATA *
|
bool Life_Safety_Point_Write_Property(
|
||||||
wp_data, BACNET_ERROR_CLASS * error_class,
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testLifeSafetyPoint(Test * pTest);
|
void testLifeSafetyPoint(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+19
-11
@@ -33,33 +33,41 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void Multistate_Output_Property_Lists(
|
void Multistate_Output_Property_Lists(
|
||||||
const int **pRequired,
|
const int **pRequired,
|
||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary);
|
const int **pProprietary);
|
||||||
bool Multistate_Output_Valid_Instance(uint32_t object_instance);
|
bool Multistate_Output_Valid_Instance(
|
||||||
unsigned Multistate_Output_Count(void);
|
uint32_t object_instance);
|
||||||
uint32_t Multistate_Output_Index_To_Instance(unsigned index);
|
unsigned Multistate_Output_Count(
|
||||||
char *Multistate_Output_Name(uint32_t object_instance);
|
void);
|
||||||
|
uint32_t Multistate_Output_Index_To_Instance(
|
||||||
|
unsigned index);
|
||||||
|
char *Multistate_Output_Name(
|
||||||
|
uint32_t object_instance);
|
||||||
|
|
||||||
int Multistate_Output_Encode_Property_APDU(uint8_t * apdu,
|
int Multistate_Output_Encode_Property_APDU(
|
||||||
|
uint8_t * apdu,
|
||||||
uint32_t object_instance,
|
uint32_t object_instance,
|
||||||
BACNET_PROPERTY_ID property,
|
BACNET_PROPERTY_ID property,
|
||||||
int32_t array_index,
|
int32_t array_index,
|
||||||
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
bool Multistate_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA *
|
bool Multistate_Output_Write_Property(
|
||||||
wp_data, BACNET_ERROR_CLASS * error_class,
|
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
BACNET_ERROR_CODE * error_code);
|
BACNET_ERROR_CODE * error_code);
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testMultistateOutput(Test * pTest);
|
void testMultistateOutput(
|
||||||
|
Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+26
-18
@@ -194,14 +194,18 @@ struct mstp_port_struct_t {
|
|||||||
/* denote intervals between N-1 and N */
|
/* denote intervals between N-1 and N */
|
||||||
/* Note: done here as functions - put into timer task or ISR
|
/* Note: done here as functions - put into timer task or ISR
|
||||||
so that you can be atomic on 8 bit microcontrollers */
|
so that you can be atomic on 8 bit microcontrollers */
|
||||||
uint16_t (*SilenceTimer)(void);
|
uint16_t(
|
||||||
void (*SilenceTimerReset)(void);
|
*SilenceTimer) (
|
||||||
|
void);
|
||||||
|
void (
|
||||||
|
*SilenceTimerReset) (
|
||||||
|
void);
|
||||||
|
|
||||||
/* A timer used to measure and generate Reply Postponed frames. It is */
|
/* A timer used to measure and generate Reply Postponed frames. It is */
|
||||||
/* incremented by a timer process and is cleared by the Master Node State */
|
/* incremented by a timer process and is cleared by the Master Node State */
|
||||||
/* Machine when a Data Expecting Reply Answer activity is completed. */
|
/* Machine when a Data Expecting Reply Answer activity is completed. */
|
||||||
/* note: we always send a reply postponed since a message other than
|
/* note: we always send a reply postponed since a message other than
|
||||||
the reply may be in the transmit queue */
|
the reply may be in the transmit queue */
|
||||||
/* uint16_t ReplyPostponedTimer; */
|
/* uint16_t ReplyPostponedTimer; */
|
||||||
|
|
||||||
/* Used to store the Source Address of a received frame. */
|
/* Used to store the Source Address of a received frame. */
|
||||||
@@ -256,32 +260,36 @@ struct mstp_port_struct_t {
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port);
|
void MSTP_Init(
|
||||||
void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t
|
volatile struct mstp_port_struct_t *mstp_port);
|
||||||
|
void MSTP_Receive_Frame_FSM(
|
||||||
|
volatile struct mstp_port_struct_t
|
||||||
*mstp_port);
|
*mstp_port);
|
||||||
bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t
|
bool MSTP_Master_Node_FSM(
|
||||||
|
volatile struct mstp_port_struct_t
|
||||||
*mstp_port);
|
*mstp_port);
|
||||||
|
|
||||||
/* returns true if line is active */
|
/* returns true if line is active */
|
||||||
bool MSTP_Line_Active(volatile struct mstp_port_struct_t *mstp_port);
|
bool MSTP_Line_Active(
|
||||||
|
volatile struct mstp_port_struct_t *mstp_port);
|
||||||
|
|
||||||
uint16_t MSTP_Create_Frame(
|
uint16_t MSTP_Create_Frame(
|
||||||
uint8_t * buffer, /* where frame is loaded */
|
uint8_t * buffer, /* where frame is loaded */
|
||||||
uint16_t buffer_len, /* amount of space available */
|
uint16_t buffer_len, /* amount of space available */
|
||||||
uint8_t frame_type, /* type of frame to send - see defines */
|
uint8_t frame_type, /* type of frame to send - see defines */
|
||||||
uint8_t destination, /* destination address */
|
uint8_t destination, /* destination address */
|
||||||
uint8_t source, /* source address */
|
uint8_t source, /* source address */
|
||||||
uint8_t * data, /* any data to be sent - may be null */
|
uint8_t * data, /* any data to be sent - may be null */
|
||||||
uint16_t data_len); /* number of bytes of data (up to 501) */
|
uint16_t data_len); /* number of bytes of data (up to 501) */
|
||||||
|
|
||||||
void MSTP_Create_And_Send_Frame(
|
void MSTP_Create_And_Send_Frame(
|
||||||
volatile struct mstp_port_struct_t *mstp_port, /* port to send from */
|
volatile struct mstp_port_struct_t *mstp_port, /* port to send from */
|
||||||
uint8_t frame_type, /* type of frame to send - see defines */
|
uint8_t frame_type, /* type of frame to send - see defines */
|
||||||
uint8_t destination, /* destination address */
|
uint8_t destination, /* destination address */
|
||||||
uint8_t source, /* source address */
|
uint8_t source, /* source address */
|
||||||
uint8_t * data, /* any data to be sent - may be null */
|
uint8_t * data, /* any data to be sent - may be null */
|
||||||
uint16_t data_len);
|
uint16_t data_len);
|
||||||
|
|
||||||
/* functions used by the MS/TP state machine to put or get data */
|
/* functions used by the MS/TP state machine to put or get data */
|
||||||
@@ -293,15 +301,15 @@ extern "C" {
|
|||||||
/* Return: amount of PDU data */
|
/* Return: amount of PDU data */
|
||||||
uint16_t MSTP_Get_Send(
|
uint16_t MSTP_Get_Send(
|
||||||
volatile struct mstp_port_struct_t *mstp_port,
|
volatile struct mstp_port_struct_t *mstp_port,
|
||||||
unsigned timeout); /* milliseconds to wait for a packet */
|
unsigned timeout); /* milliseconds to wait for a packet */
|
||||||
/* for the MS/TP state machine to use for getting the reply for
|
/* for the MS/TP state machine to use for getting the reply for
|
||||||
Data-Expecting-Reply Frame */
|
Data-Expecting-Reply Frame */
|
||||||
/* Return: amount of PDU data */
|
/* Return: amount of PDU data */
|
||||||
uint16_t MSTP_Get_Reply(
|
uint16_t MSTP_Get_Reply(
|
||||||
volatile struct mstp_port_struct_t *mstp_port,
|
volatile struct mstp_port_struct_t *mstp_port,
|
||||||
unsigned timeout); /* milliseconds to wait for a packet */
|
unsigned timeout); /* milliseconds to wait for a packet */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -37,14 +37,16 @@
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
const char *mstptext_receive_state(int index);
|
const char *mstptext_receive_state(
|
||||||
const char *mstptext_master_state(int index);
|
int index);
|
||||||
const char *mstptext_frame_type(int index);
|
const char *mstptext_master_state(
|
||||||
|
int index);
|
||||||
|
const char *mstptext_frame_type(
|
||||||
|
int index);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+24
-13
@@ -48,34 +48,45 @@ typedef struct bacnet_npdu_data_t {
|
|||||||
BACNET_MESSAGE_PRIORITY priority;
|
BACNET_MESSAGE_PRIORITY priority;
|
||||||
/* optional network message info */
|
/* optional network message info */
|
||||||
BACNET_NETWORK_MESSAGE_TYPE network_message_type; /* optional */
|
BACNET_NETWORK_MESSAGE_TYPE network_message_type; /* optional */
|
||||||
uint16_t vendor_id; /* optional, if net message type is > 0x80 */
|
uint16_t vendor_id; /* optional, if net message type is > 0x80 */
|
||||||
uint8_t hop_count;
|
uint8_t hop_count;
|
||||||
} BACNET_NPDU_DATA;
|
} BACNET_NPDU_DATA;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
uint8_t npdu_encode_max_seg_max_apdu(int max_segs, int max_apdu);
|
uint8_t npdu_encode_max_seg_max_apdu(
|
||||||
|
int max_segs,
|
||||||
|
int max_apdu);
|
||||||
|
|
||||||
int npdu_encode_pdu(uint8_t * npdu,
|
int npdu_encode_pdu(
|
||||||
|
uint8_t * npdu,
|
||||||
BACNET_ADDRESS * dest,
|
BACNET_ADDRESS * dest,
|
||||||
BACNET_ADDRESS * src, BACNET_NPDU_DATA * npdu_data);
|
BACNET_ADDRESS * src,
|
||||||
|
BACNET_NPDU_DATA * npdu_data);
|
||||||
|
|
||||||
void npdu_encode_npdu_data(BACNET_NPDU_DATA * npdu,
|
void npdu_encode_npdu_data(
|
||||||
bool data_expecting_reply, BACNET_MESSAGE_PRIORITY priority);
|
BACNET_NPDU_DATA * npdu,
|
||||||
|
bool data_expecting_reply,
|
||||||
|
BACNET_MESSAGE_PRIORITY priority);
|
||||||
|
|
||||||
void npdu_copy_data(BACNET_NPDU_DATA * dest, BACNET_NPDU_DATA * src);
|
void npdu_copy_data(
|
||||||
|
BACNET_NPDU_DATA * dest,
|
||||||
|
BACNET_NPDU_DATA * src);
|
||||||
|
|
||||||
int npdu_decode(uint8_t * npdu,
|
int npdu_decode(
|
||||||
|
uint8_t * npdu,
|
||||||
BACNET_ADDRESS * dest,
|
BACNET_ADDRESS * dest,
|
||||||
BACNET_ADDRESS * src, BACNET_NPDU_DATA * npdu_data);
|
BACNET_ADDRESS * src,
|
||||||
|
BACNET_NPDU_DATA * npdu_data);
|
||||||
|
|
||||||
void npdu_handler(BACNET_ADDRESS * src, /* source address */
|
void npdu_handler(
|
||||||
uint8_t * pdu, /* PDU data */
|
BACNET_ADDRESS * src, /* source address */
|
||||||
|
uint8_t * pdu, /* PDU data */
|
||||||
uint16_t pdu_len); /* length PDU */
|
uint16_t pdu_len); /* length PDU */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user