running the indent on the files.

This commit is contained in:
skarg
2006-02-18 23:11:25 +00:00
parent b1d46ffa8c
commit d6a891f0d1
58 changed files with 4781 additions and 5862 deletions
+28 -46
View File
@@ -35,63 +35,45 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/* 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,
int32_t high_limit,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance);
void Send_WhoHas_Object(int32_t low_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_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,
uint32_t object_instance,
char *object_name);
/* returns the invoke ID for confirmed request, or 0 if failed */
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);
void Send_I_Have(uint32_t device_id,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance, char *object_name);
/* 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,
uint32_t object_instance,
BACNET_PROPERTY_ID object_property,
BACNET_APPLICATION_DATA_VALUE *object_value,
uint8_t priority,
int32_t array_index);
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_Reinitialize_Device_Request(
uint32_t device_id,
BACNET_REINITIALIZED_STATE state,
char *password);
uint8_t Send_Write_Property_Request(uint32_t device_id, // destination device
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID object_property,
BACNET_APPLICATION_DATA_VALUE * object_value,
uint8_t priority, int32_t array_index);
/* 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 */
BACNET_COMMUNICATION_ENABLE_DISABLE state,
char *password); /* NULL=optional */
uint8_t Send_Reinitialize_Device_Request(uint32_t device_id,
BACNET_REINITIALIZED_STATE state, char *password);
/* 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 */
BACNET_COMMUNICATION_ENABLE_DISABLE state, char *password); /* NULL=optional */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+72 -106
View File
@@ -41,116 +41,82 @@
#include "ao.h"
#include "bacfile.h"
void handler_atomic_read_file(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_DATA *service_data)
void handler_atomic_read_file(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_ATOMIC_READ_FILE_DATA data;
int len = 0;
int pdu_len = 0;
BACNET_ADDRESS my_address;
bool send = false;
bool error = false;
int bytes_sent = 0;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
BACNET_ATOMIC_READ_FILE_DATA data;
int len = 0;
int pdu_len = 0;
BACNET_ADDRESS my_address;
bool send = false;
bool error = false;
int bytes_sent = 0;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
fprintf(stderr,"Received Atomic-Read-File Request!\n");
len = arf_decode_service_request(
service_request,
service_len,
&data);
if (len < 0)
fprintf(stderr,"Unable to decode Atomic-Read-File Request!\n");
// prepare a reply
datalink_get_my_address(&my_address);
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
src,
&my_address,
false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// bad decoding - send an abort
if (len < 0)
{
pdu_len += abort_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_OTHER);
fprintf(stderr,"Sending Abort!\n");
send = true;
}
else if (service_data->segmented_message)
{
pdu_len += abort_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
fprintf(stderr,"Sending Abort!\n");
send = true;
}
else
{
if (data.access == FILE_STREAM_ACCESS)
{
if (data.type.stream.requestedOctetCount <
octetstring_capacity(&data.fileData))
{
if (bacfile_read_data(&data))
{
pdu_len += arf_ack_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
&data);
send = true;
}
else
{
send = true;
error = true;
}
}
else
{
pdu_len += abort_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
fprintf(stderr,"Sending Abort!\n");
fprintf(stderr, "Received Atomic-Read-File Request!\n");
len = arf_decode_service_request(service_request, service_len, &data);
if (len < 0)
fprintf(stderr, "Unable to decode Atomic-Read-File Request!\n");
// prepare a reply
datalink_get_my_address(&my_address);
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], src, &my_address, false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// bad decoding - send an abort
if (len < 0) {
pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER);
fprintf(stderr, "Sending Abort!\n");
send = true;
}
} else if (service_data->segmented_message) {
pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
fprintf(stderr, "Sending Abort!\n");
send = true;
} else {
if (data.access == FILE_STREAM_ACCESS) {
if (data.type.stream.requestedOctetCount <
octetstring_capacity(&data.fileData)) {
if (bacfile_read_data(&data)) {
pdu_len +=
arf_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
send = true;
} else {
send = true;
error = true;
}
} else {
pdu_len +=
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
fprintf(stderr, "Sending Abort!\n");
send = true;
}
} else {
error_class = ERROR_CLASS_SERVICES;
error_code = ERROR_CODE_INVALID_FILE_ACCESS_METHOD;
send = true;
error = true;
}
}
else
{
error_class = ERROR_CLASS_SERVICES;
error_code = ERROR_CODE_INVALID_FILE_ACCESS_METHOD;
send = true;
error = true;
if (error) {
pdu_len += bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_ATOMIC_READ_FILE, error_class, error_code);
fprintf(stderr, "Sending Error!\n");
send = true;
}
if (send) {
bytes_sent = datalink_send_pdu(src, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno));
}
}
if (error)
{
pdu_len += bacerror_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_ATOMIC_READ_FILE,
error_class,
error_code);
fprintf(stderr,"Sending Error!\n");
send = true;
}
if (send)
{
bytes_sent = datalink_send_pdu(
src, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to send PDU (%s)!\n", strerror(errno));
}
return;
return;
}
+33 -45
View File
@@ -47,54 +47,42 @@
// that someone can read from us. It is common to
// use the description as the file name.
#if BACFILE
void handler_atomic_read_file_ack(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_ACK_DATA *service_data)
void handler_atomic_read_file_ack(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
{
int len = 0;
BACNET_ATOMIC_READ_FILE_DATA data;
FILE *pFile = NULL;
char *pFilename = NULL;
uint32_t instance = 0;
int len = 0;
BACNET_ATOMIC_READ_FILE_DATA data;
FILE *pFile = NULL;
char *pFilename = NULL;
uint32_t instance = 0;
(void)src;
// get the file instance from the tsm data before freeing it
instance = bacfile_instance_from_tsm(service_data->invoke_id);
len = arf_ack_decode_service_request(
service_request,
service_len,
&data);
fprintf(stderr,"Received Read-File Ack!\n");
if ((len > 0) && (instance <= BACNET_MAX_INSTANCE))
{
// write the data received to the file specified
if (data.access == FILE_STREAM_ACCESS)
{
pFilename = bacfile_name(instance);
if (pFilename)
{
pFile = fopen(pFilename, "rb");
if (pFile)
{
(void)fseek(pFile,
data.type.stream.fileStartPosition,
SEEK_SET);
if (fwrite(octetstring_value(&data.fileData),
octetstring_length(&data.fileData),1,pFile) != 1)
fprintf(stderr,"Failed to write to %s (%u)!\n",
pFilename, instance);
fclose(pFile);
(void) src;
// get the file instance from the tsm data before freeing it
instance = bacfile_instance_from_tsm(service_data->invoke_id);
len = arf_ack_decode_service_request(service_request,
service_len, &data);
fprintf(stderr, "Received Read-File Ack!\n");
if ((len > 0) && (instance <= BACNET_MAX_INSTANCE)) {
// write the data received to the file specified
if (data.access == FILE_STREAM_ACCESS) {
pFilename = bacfile_name(instance);
if (pFilename) {
pFile = fopen(pFilename, "rb");
if (pFile) {
(void) fseek(pFile,
data.type.stream.fileStartPosition, SEEK_SET);
if (fwrite(octetstring_value(&data.fileData),
octetstring_length(&data.fileData), 1,
pFile) != 1)
fprintf(stderr, "Failed to write to %s (%u)!\n",
pFilename, instance);
fclose(pFile);
}
}
} else if (data.access == FILE_RECORD_ACCESS) {
// FIXME: add handling for Record Access
}
}
}
else if (data.access == FILE_RECORD_ACCESS)
{
// FIXME: add handling for Record Access
}
}
}
#endif
+67 -97
View File
@@ -40,106 +40,76 @@
static char *My_Password = "AnnaRoseKarg";
void handler_device_communication_control(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_DATA *service_data)
void handler_device_communication_control(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
uint16_t timeDuration = 0;
BACNET_COMMUNICATION_ENABLE_DISABLE state = COMMUNICATION_ENABLE;
BACNET_CHARACTER_STRING password;
int len = 0;
int pdu_len = 0;
BACNET_ADDRESS my_address;
int bytes_sent = 0;
uint16_t timeDuration = 0;
BACNET_COMMUNICATION_ENABLE_DISABLE state = COMMUNICATION_ENABLE;
BACNET_CHARACTER_STRING password;
int len = 0;
int pdu_len = 0;
BACNET_ADDRESS my_address;
int bytes_sent = 0;
// decode the service request only
len = dcc_decode_service_request(
service_request,
service_len,
&timeDuration,
&state,
&password);
fprintf(stderr,"DeviceCommunicationControl!\n");
if (len > 0)
fprintf(stderr,"DeviceCommunicationControl: "
"timeout=%u state=%u password=%s\n",
(unsigned)timeDuration,
(unsigned)state,
characterstring_value(&password));
else
fprintf(stderr,"DeviceCommunicationControl: "
"Unable to decode request!\n");
// prepare a reply
datalink_get_my_address(&my_address);
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
src,
&my_address,
false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// bad decoding or something we didn't understand - send an abort
if (len == -1)
{
pdu_len += abort_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_OTHER);
fprintf(stderr,"DeviceCommunicationControl: "
"Sending Abort - could not decode.\n");
}
else if (service_data->segmented_message)
{
pdu_len += abort_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
fprintf(stderr,"DeviceCommunicationControl: "
"Sending Abort - segmented message.\n");
}
else if (state >= MAX_BACNET_COMMUNICATION_ENABLE_DISABLE)
{
pdu_len += reject_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
REJECT_REASON_UNDEFINED_ENUMERATION);
fprintf(stderr,"DeviceCommunicationControl: "
"Sending Reject - undefined enumeration\n");
}
else
{
if (characterstring_ansi_same(&password,My_Password))
{
pdu_len += encode_simple_ack(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL);
fprintf(stderr,"DeviceCommunicationControl: "
"Sending Simple Ack!\n");
dcc_set_status_duration(state,timeDuration);
}
// decode the service request only
len = dcc_decode_service_request(service_request,
service_len, &timeDuration, &state, &password);
fprintf(stderr, "DeviceCommunicationControl!\n");
if (len > 0)
fprintf(stderr, "DeviceCommunicationControl: "
"timeout=%u state=%u password=%s\n",
(unsigned) timeDuration,
(unsigned) state, characterstring_value(&password));
else
{
pdu_len += bacerror_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
ERROR_CLASS_SERVICES,
ERROR_CODE_PASSWORD_FAILURE);
fprintf(stderr,"DeviceCommunicationControl: "
"Sending Error - password failure.\n");
fprintf(stderr, "DeviceCommunicationControl: "
"Unable to decode request!\n");
// prepare a reply
datalink_get_my_address(&my_address);
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], src, &my_address, false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// bad decoding or something we didn't understand - send an abort
if (len == -1) {
pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER);
fprintf(stderr, "DeviceCommunicationControl: "
"Sending Abort - could not decode.\n");
} else if (service_data->segmented_message) {
pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
fprintf(stderr, "DeviceCommunicationControl: "
"Sending Abort - segmented message.\n");
} else if (state >= MAX_BACNET_COMMUNICATION_ENABLE_DISABLE) {
pdu_len += reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION);
fprintf(stderr, "DeviceCommunicationControl: "
"Sending Reject - undefined enumeration\n");
} else {
if (characterstring_ansi_same(&password, My_Password)) {
pdu_len += encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL);
fprintf(stderr, "DeviceCommunicationControl: "
"Sending Simple Ack!\n");
dcc_set_status_duration(state, timeDuration);
} else {
pdu_len +=
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
ERROR_CLASS_SERVICES, ERROR_CODE_PASSWORD_FAILURE);
fprintf(stderr,
"DeviceCommunicationControl: "
"Sending Error - password failure.\n");
}
}
}
bytes_sent = datalink_send_pdu(
src, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"DeviceCommunicationControl: "
"Failed to send PDU (%s)!\n",
strerror(errno));
bytes_sent = datalink_send_pdu(src, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr, "DeviceCommunicationControl: "
"Failed to send PDU (%s)!\n", strerror(errno));
return;
return;
}
+30 -49
View File
@@ -32,61 +32,42 @@
#include "iam.h"
#include "address.h"
void handler_i_am_add(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src)
void handler_i_am_add(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
{
int len = 0;
uint32_t device_id = 0;
unsigned max_apdu = 0;
int segmentation = 0;
uint16_t vendor_id = 0;
int len = 0;
uint32_t device_id = 0;
unsigned max_apdu = 0;
int segmentation = 0;
uint16_t vendor_id = 0;
(void)service_len;
len = iam_decode_service_request(
service_request,
&device_id,
&max_apdu,
&segmentation,
&vendor_id);
fprintf(stderr,"Received I-Am Request");
if (len != -1)
{
fprintf(stderr," from %u!\n",device_id);
address_add(device_id,
max_apdu,
src);
}
else
fprintf(stderr,"!\n");
(void) service_len;
len = iam_decode_service_request(service_request,
&device_id, &max_apdu, &segmentation, &vendor_id);
fprintf(stderr, "Received I-Am Request");
if (len != -1) {
fprintf(stderr, " from %u!\n", device_id);
address_add(device_id, max_apdu, src);
} else
fprintf(stderr, "!\n");
return;
return;
}
void handler_i_am_bind(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src)
void handler_i_am_bind(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
{
int len = 0;
uint32_t device_id = 0;
unsigned max_apdu = 0;
int segmentation = 0;
uint16_t vendor_id = 0;
int len = 0;
uint32_t device_id = 0;
unsigned max_apdu = 0;
int segmentation = 0;
uint16_t vendor_id = 0;
(void)service_len;
len = iam_decode_service_request(
service_request,
&device_id,
&max_apdu,
&segmentation,
&vendor_id);
// only add address if requested to bind
address_add_binding(device_id,
max_apdu,
src);
(void) service_len;
len = iam_decode_service_request(service_request,
&device_id, &max_apdu, &segmentation, &vendor_id);
// only add address if requested to bind
address_add_binding(device_id, max_apdu, src);
return;
return;
}
+17 -24
View File
@@ -32,31 +32,24 @@
#include "bactext.h"
#include "ihave.h"
void handler_i_have(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src)
void handler_i_have(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
{
int len = 0;
BACNET_I_HAVE_DATA data;
int len = 0;
BACNET_I_HAVE_DATA data;
(void)service_len;
(void)src;
len = ihave_decode_service_request(
service_request,
service_len,
&data);
if (len != -1)
{
fprintf(stderr,"I-Have: %s %d from %s %u!\r\n",
bactext_object_type_name(data.object_id.type),
data.object_id.instance,
bactext_object_type_name(data.device_id.type),
data.device_id.instance);
}
else
fprintf(stderr,"I-Have: received, but unable to decode!\n");
(void) service_len;
(void) src;
len = ihave_decode_service_request(service_request,
service_len, &data);
if (len != -1) {
fprintf(stderr, "I-Have: %s %d from %s %u!\r\n",
bactext_object_type_name(data.object_id.type),
data.object_id.instance,
bactext_object_type_name(data.device_id.type),
data.device_id.instance);
} else
fprintf(stderr, "I-Have: received, but unable to decode!\n");
return;
return;
}
+65 -90
View File
@@ -40,99 +40,74 @@
static BACNET_CHARACTER_STRING My_Password;
void handler_reinitialize_device(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_DATA *service_data)
void handler_reinitialize_device(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_REINITIALIZED_STATE state;
BACNET_CHARACTER_STRING password;
int len = 0;
int pdu_len = 0;
BACNET_ADDRESS my_address;
int bytes_sent = 0;
BACNET_REINITIALIZED_STATE state;
BACNET_CHARACTER_STRING password;
int len = 0;
int pdu_len = 0;
BACNET_ADDRESS my_address;
int bytes_sent = 0;
// decode the service request only
len = rd_decode_service_request(
service_request,
service_len,
&state,
&password);
fprintf(stderr,"ReinitializeDevice!\n");
if (len > 0)
fprintf(stderr,"ReinitializeDevice: state=%u password=%s\n",
(unsigned)state,
characterstring_value(&password));
else
fprintf(stderr,"ReinitializeDevice: Unable to decode request!\n");
// prepare a reply
datalink_get_my_address(&my_address);
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
src,
&my_address,
false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// bad decoding or something we didn't understand - send an abort
if (len == -1)
{
pdu_len += abort_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_OTHER);
fprintf(stderr,"ReinitializeDevice: Sending Abort - could not decode.\n");
}
else if (service_data->segmented_message)
{
pdu_len += abort_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
fprintf(stderr,"ReinitializeDevice: Sending Abort - segmented message.\n");
}
else if (state >= MAX_BACNET_REINITIALIZED_STATE)
{
pdu_len += reject_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
REJECT_REASON_UNDEFINED_ENUMERATION);
fprintf(stderr,"ReinitializeDevice: Sending Reject - undefined enumeration\n");
}
else
{
characterstring_init_ansi(&My_Password,"Jesus");
if (characterstring_same(&password,&My_Password))
{
pdu_len += encode_simple_ack(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_REINITIALIZE_DEVICE);
fprintf(stderr,"ReinitializeDevice: Sending Simple Ack!\n");
/* FIXME: now you can reboot, restart, quit, or something clever */
/* Note: you can use a mix of state and password to do specific stuff */
/* Note: if you don't do something clever like actually restart,
you probably should clear any DCC status and timeouts */
}
// decode the service request only
len = rd_decode_service_request(service_request,
service_len, &state, &password);
fprintf(stderr, "ReinitializeDevice!\n");
if (len > 0)
fprintf(stderr, "ReinitializeDevice: state=%u password=%s\n",
(unsigned) state, characterstring_value(&password));
else
{
pdu_len += bacerror_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
ERROR_CLASS_SERVICES,
ERROR_CODE_PASSWORD_FAILURE);
fprintf(stderr,"ReinitializeDevice: Sending Error - password failure.\n");
fprintf(stderr, "ReinitializeDevice: Unable to decode request!\n");
// prepare a reply
datalink_get_my_address(&my_address);
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], src, &my_address, false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// bad decoding or something we didn't understand - send an abort
if (len == -1) {
pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER);
fprintf(stderr,
"ReinitializeDevice: Sending Abort - could not decode.\n");
} else if (service_data->segmented_message) {
pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
fprintf(stderr,
"ReinitializeDevice: Sending Abort - segmented message.\n");
} else if (state >= MAX_BACNET_REINITIALIZED_STATE) {
pdu_len += reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, REJECT_REASON_UNDEFINED_ENUMERATION);
fprintf(stderr,
"ReinitializeDevice: Sending Reject - undefined enumeration\n");
} else {
characterstring_init_ansi(&My_Password, "Jesus");
if (characterstring_same(&password, &My_Password)) {
pdu_len += encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_REINITIALIZE_DEVICE);
fprintf(stderr, "ReinitializeDevice: Sending Simple Ack!\n");
/* FIXME: now you can reboot, restart, quit, or something clever */
/* Note: you can use a mix of state and password to do specific stuff */
/* Note: if you don't do something clever like actually restart,
you probably should clear any DCC status and timeouts */
} else {
pdu_len +=
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
ERROR_CLASS_SERVICES, ERROR_CODE_PASSWORD_FAILURE);
fprintf(stderr,
"ReinitializeDevice: Sending Error - password failure.\n");
}
}
}
bytes_sent = datalink_send_pdu(
src, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"ReinitializeDevice: Failed to send PDU (%s)!\n",
strerror(errno));
bytes_sent = datalink_send_pdu(src, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr, "ReinitializeDevice: Failed to send PDU (%s)!\n",
strerror(errno));
return;
return;
}
+136 -194
View File
@@ -43,206 +43,148 @@
#include "bacfile.h"
#endif
static uint8_t Temp_Buf[MAX_APDU] = {0};
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
void handler_read_property(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_DATA *service_data)
void handler_read_property(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_READ_PROPERTY_DATA data;
int len = 0;
int pdu_len = 0;
BACNET_ADDRESS my_address;
bool send = false;
bool error = false;
int bytes_sent = 0;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
BACNET_READ_PROPERTY_DATA data;
int len = 0;
int pdu_len = 0;
BACNET_ADDRESS my_address;
bool send = false;
bool error = false;
int bytes_sent = 0;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
len = rp_decode_service_request(
service_request,
service_len,
&data);
if (len <= 0)
fprintf(stderr,"Unable to decode Read-Property Request!\n");
// prepare a reply
datalink_get_my_address(&my_address);
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
src,
&my_address,
false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// bad decoding - send an abort
if (len == -1)
{
pdu_len += abort_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_OTHER);
fprintf(stderr,"Sending Abort!\n");
send = true;
}
else if (service_data->segmented_message)
{
pdu_len += abort_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
fprintf(stderr,"Sending Abort!\n");
send = true;
}
else
{
switch (data.object_type)
{
case OBJECT_DEVICE:
// FIXME: probably need a length limitation sent with encode
if (data.object_instance == Device_Object_Instance_Number())
{
len = Device_Encode_Property_APDU(
&Temp_Buf[0],
data.object_property,
data.array_index,
&error_class,
&error_code);
if (len >= 0)
{
// encode the APDU portion of the packet
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
len = rp_decode_service_request(service_request, service_len, &data);
if (len <= 0)
fprintf(stderr, "Unable to decode Read-Property Request!\n");
// prepare a reply
datalink_get_my_address(&my_address);
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], src, &my_address, false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// bad decoding - send an abort
if (len == -1) {
pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER);
fprintf(stderr, "Sending Abort!\n");
send = true;
} else if (service_data->segmented_message) {
pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
fprintf(stderr, "Sending Abort!\n");
send = true;
} else {
switch (data.object_type) {
case OBJECT_DEVICE:
// FIXME: probably need a length limitation sent with encode
pdu_len += rp_ack_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
&data);
fprintf(stderr,"Sending Read Property Ack!\n");
send = true;
}
else
if (data.object_instance == Device_Object_Instance_Number()) {
len = Device_Encode_Property_APDU(&Temp_Buf[0],
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
// encode the APDU portion of the packet
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
// FIXME: probably need a length limitation sent with encode
pdu_len +=
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
fprintf(stderr, "Sending Read Property Ack!\n");
send = true;
} else
error = true;
} else
error = true;
break;
case OBJECT_ANALOG_INPUT:
if (Analog_Input_Valid_Instance(data.object_instance)) {
len = Analog_Input_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
// encode the APDU portion of the packet
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
// FIXME: probably need a length limitation sent with encode
pdu_len +=
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
fprintf(stderr, "Sending Read Property Ack!\n");
send = true;
} else
error = true;
} else
error = true;
break;
case OBJECT_ANALOG_OUTPUT:
if (Analog_Output_Valid_Instance(data.object_instance)) {
len = Analog_Output_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
// encode the APDU portion of the packet
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
// FIXME: probably need a length limitation sent with encode
pdu_len +=
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
fprintf(stderr, "Sending Read Property Ack!\n");
send = true;
} else
error = true;
} else
error = true;
break;
#if BACFILE
case OBJECT_FILE:
if (bacfile_valid_instance(data.object_instance)) {
len = bacfile_encode_property_apdu(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
// encode the APDU portion of the packet
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
// FIXME: probably need a length limitation sent with encode
pdu_len +=
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
fprintf(stderr, "Sending Read Property Ack!\n");
send = true;
} else
error = true;
} else
error = true;
break;
#endif
default:
error = true;
break;
}
else
error = true;
break;
case OBJECT_ANALOG_INPUT:
if (Analog_Input_Valid_Instance(data.object_instance))
{
len = Analog_Input_Encode_Property_APDU(
&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index,
&error_class,
&error_code);
if (len >= 0)
{
// encode the APDU portion of the packet
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
// FIXME: probably need a length limitation sent with encode
pdu_len += rp_ack_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
&data);
fprintf(stderr,"Sending Read Property Ack!\n");
send = true;
}
else
error = true;
}
else
error = true;
break;
case OBJECT_ANALOG_OUTPUT:
if (Analog_Output_Valid_Instance(data.object_instance))
{
len = Analog_Output_Encode_Property_APDU(
&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index,
&error_class,
&error_code);
if (len >= 0)
{
// encode the APDU portion of the packet
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
// FIXME: probably need a length limitation sent with encode
pdu_len += rp_ack_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
&data);
fprintf(stderr,"Sending Read Property Ack!\n");
send = true;
}
else
error = true;
}
else
error = true;
break;
#if BACFILE
case OBJECT_FILE:
if (bacfile_valid_instance(data.object_instance))
{
len = bacfile_encode_property_apdu(
&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index,
&error_class,
&error_code);
if (len >= 0)
{
// encode the APDU portion of the packet
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
// FIXME: probably need a length limitation sent with encode
pdu_len += rp_ack_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
&data);
fprintf(stderr,"Sending Read Property Ack!\n");
send = true;
}
else
error = true;
}
else
error = true;
break;
#endif
default:
error = true;
break;
}
}
if (error)
{
pdu_len += bacerror_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_READ_PROPERTY,
error_class,
error_code);
fprintf(stderr,"Sending Read Property Error!\n");
send = true;
}
if (send)
{
bytes_sent = datalink_send_pdu(
src, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to send PDU (%s)!\n", strerror(errno));
}
if (error) {
pdu_len += bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code);
fprintf(stderr, "Sending Read Property Error!\n");
send = true;
}
if (send) {
bytes_sent = datalink_send_pdu(src, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno));
}
return;
return;
}
+60 -73
View File
@@ -42,85 +42,72 @@
#include "txbuf.h"
/* for debugging... */
static void PrintReadPropertyData(BACNET_READ_PROPERTY_DATA *data)
static void PrintReadPropertyData(BACNET_READ_PROPERTY_DATA * data)
{
BACNET_APPLICATION_DATA_VALUE value; /* for decode value data */
int len = 0;
uint8_t *application_data;
int application_data_len;
bool first_value = true;
bool print_brace = false;
BACNET_APPLICATION_DATA_VALUE value; /* for decode value data */
int len = 0;
uint8_t *application_data;
int application_data_len;
bool first_value = true;
bool print_brace = false;
if (data)
{
#if 0
if (data->array_index == BACNET_ARRAY_ALL)
fprintf(stderr,"%s #%u %s\n",
bactext_object_type_name(data->object_type),
data->object_instance,
bactext_property_name(data->object_property));
else
fprintf(stderr,"%s #%u %s[%d]\n",
bactext_object_type_name(data->object_type),
data->object_instance,
bactext_property_name(data->object_property),
data->array_index);
#endif
application_data = data->application_data;
application_data_len = data->application_data_len;
/* value? need to loop until all of the len is gone... */
for (;;)
{
len = bacapp_decode_application_data(
application_data,
application_data_len,
&value);
if (first_value && (len < application_data_len))
{
first_value = false;
fprintf(stdout,"{");
print_brace = true;
}
bacapp_print_value(stdout,&value,data->object_property);
if (len)
{
if (len < application_data_len)
{
application_data += len;
application_data_len -= len;
/* there's more! */
fprintf(stdout,",");
}
if (data) {
#if 0
if (data->array_index == BACNET_ARRAY_ALL)
fprintf(stderr, "%s #%u %s\n",
bactext_object_type_name(data->object_type),
data->object_instance,
bactext_property_name(data->object_property));
else
break;
}
else
break;
fprintf(stderr, "%s #%u %s[%d]\n",
bactext_object_type_name(data->object_type),
data->object_instance,
bactext_property_name(data->object_property),
data->array_index);
#endif
application_data = data->application_data;
application_data_len = data->application_data_len;
/* value? need to loop until all of the len is gone... */
for (;;) {
len = bacapp_decode_application_data(application_data,
application_data_len, &value);
if (first_value && (len < application_data_len)) {
first_value = false;
fprintf(stdout, "{");
print_brace = true;
}
bacapp_print_value(stdout, &value, data->object_property);
if (len) {
if (len < application_data_len) {
application_data += len;
application_data_len -= len;
/* there's more! */
fprintf(stdout, ",");
} else
break;
} else
break;
}
if (print_brace)
fprintf(stdout, "}");
fprintf(stdout, "\r\n");
}
if (print_brace)
fprintf(stdout,"}");
fprintf(stdout,"\r\n");
}
}
void handler_read_property_ack(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_ACK_DATA *service_data)
void handler_read_property_ack(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
{
int len = 0;
BACNET_READ_PROPERTY_DATA data;
int len = 0;
BACNET_READ_PROPERTY_DATA data;
(void)src;
(void)service_data; /* we could use these... */
len = rp_ack_decode_service_request(
service_request,
service_len,
&data);
#if 0
fprintf(stderr,"Received Read-Property Ack!\n");
#endif
if (len > 0)
PrintReadPropertyData(&data);
(void) src;
(void) service_data; /* we could use these... */
len = rp_ack_decode_service_request(service_request,
service_len, &data);
#if 0
fprintf(stderr, "Received Read-Property Ack!\n");
#endif
if (len > 0)
PrintReadPropertyData(&data);
}
+43 -57
View File
@@ -35,65 +35,51 @@
#include "device.h"
#include "client.h"
void handler_who_has(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src)
void handler_who_has(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
{
int len = 0;
BACNET_WHO_HAS_DATA data;
bool directed_to_me = false;
int object_type = 0;
uint32_t object_instance = 0;
char *object_name = NULL;
bool found = false;
int len = 0;
BACNET_WHO_HAS_DATA data;
bool directed_to_me = false;
int object_type = 0;
uint32_t object_instance = 0;
char *object_name = NULL;
bool found = false;
(void)src;
len = whohas_decode_service_request(
service_request,
service_len,
&data);
if (len > 0)
{
if ((data.low_limit == -1) || (data.high_limit == -1))
directed_to_me = true;
else if ((Device_Object_Instance_Number() >= (uint32_t)data.low_limit) &&
(Device_Object_Instance_Number() <= (uint32_t)data.high_limit))
directed_to_me = true;
if (directed_to_me)
{
/* do we have such an object? If so, send an I-Have.
note: we should have only 1 of such an object */
if (data.object_name)
{
/* valid name in my device? */
object_name = characterstring_value(&data.object.name);
found = Device_Valid_Object_Name(
object_name,
&object_type,
&object_instance);
if (found)
Send_I_Have(
Device_Object_Instance_Number(),
object_type,
object_instance,
object_name);
}
else
{
/* valid object in my device? */
object_name = Device_Valid_Object_Id(
data.object.identifier.type,
data.object.identifier.instance);
if (object_name)
Send_I_Have(
Device_Object_Instance_Number(),
data.object.identifier.type,
data.object.identifier.instance,
object_name);
}
(void) src;
len = whohas_decode_service_request(service_request,
service_len, &data);
if (len > 0) {
if ((data.low_limit == -1) || (data.high_limit == -1))
directed_to_me = true;
else if ((Device_Object_Instance_Number() >=
(uint32_t) data.low_limit)
&& (Device_Object_Instance_Number() <=
(uint32_t) data.high_limit))
directed_to_me = true;
if (directed_to_me) {
/* do we have such an object? If so, send an I-Have.
note: we should have only 1 of such an object */
if (data.object_name) {
/* valid name in my device? */
object_name = characterstring_value(&data.object.name);
found = Device_Valid_Object_Name(object_name,
&object_type, &object_instance);
if (found)
Send_I_Have(Device_Object_Instance_Number(),
object_type, object_instance, object_name);
} else {
/* valid object in my device? */
object_name =
Device_Valid_Object_Id(data.object.identifier.type,
data.object.identifier.instance);
if (object_name)
Send_I_Have(Device_Object_Instance_Number(),
data.object.identifier.type,
data.object.identifier.instance, object_name);
}
}
}
}
return;
return;
}
+18 -24
View File
@@ -37,31 +37,25 @@
/* global flag to send an I-Am */
bool I_Am_Request = true;
void handler_who_is(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src)
void handler_who_is(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
{
int len = 0;
int32_t low_limit = 0;
int32_t high_limit = 0;
int len = 0;
int32_t low_limit = 0;
int32_t high_limit = 0;
(void)src;
len = whois_decode_service_request(
service_request,
service_len,
&low_limit,
&high_limit);
/* in our simple system, we just set a flag and let the main loop
send the I-Am request. */
if (len == 0)
I_Am_Request = true;
else if (len != -1)
{
if ((Device_Object_Instance_Number() >= (uint32_t)low_limit) &&
(Device_Object_Instance_Number() <= (uint32_t)high_limit))
I_Am_Request = true;
}
(void) src;
len = whois_decode_service_request(service_request,
service_len, &low_limit, &high_limit);
/* in our simple system, we just set a flag and let the main loop
send the I-Am request. */
if (len == 0)
I_Am_Request = true;
else if (len != -1) {
if ((Device_Object_Instance_Number() >= (uint32_t) low_limit) &&
(Device_Object_Instance_Number() <= (uint32_t) high_limit))
I_Am_Request = true;
}
return;
return;
}
+91 -122
View File
@@ -43,132 +43,101 @@
#include "bacfile.h"
#endif
void handler_write_property(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_DATA *service_data)
void handler_write_property(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_WRITE_PROPERTY_DATA wp_data;
int len = 0;
int pdu_len = 0;
BACNET_ADDRESS my_address;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
int bytes_sent = 0;
BACNET_WRITE_PROPERTY_DATA wp_data;
int len = 0;
int pdu_len = 0;
BACNET_ADDRESS my_address;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
int bytes_sent = 0;
// decode the service request only
len = wp_decode_service_request(
service_request,
service_len,
&wp_data);
fprintf(stderr,"Received Write-Property Request!\n");
if (len > 0)
fprintf(stderr,"type=%u instance=%u property=%u index=%d\n",
wp_data.object_type,
wp_data.object_instance,
wp_data.object_property,
wp_data.array_index);
else
fprintf(stderr,"Unable to decode Write-Property Request!\n");
// prepare a reply
datalink_get_my_address(&my_address);
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
src,
&my_address,
false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// bad decoding or something we didn't understand - send an abort
if (len == -1)
{
pdu_len += abort_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_OTHER);
fprintf(stderr,"Sending Abort!\n");
}
else if (service_data->segmented_message)
{
pdu_len += abort_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
fprintf(stderr,"Sending Abort!\n");
}
else
{
switch (wp_data.object_type)
{
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data,&error_class,&error_code))
{
pdu_len += encode_simple_ack(
&Handler_Transmit_Buffer[pdu_len],
// decode the service request only
len = wp_decode_service_request(service_request,
service_len, &wp_data);
fprintf(stderr, "Received Write-Property Request!\n");
if (len > 0)
fprintf(stderr, "type=%u instance=%u property=%u index=%d\n",
wp_data.object_type,
wp_data.object_instance,
wp_data.object_property, wp_data.array_index);
else
fprintf(stderr, "Unable to decode Write-Property Request!\n");
// prepare a reply
datalink_get_my_address(&my_address);
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], src, &my_address, false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// bad decoding or something we didn't understand - send an abort
if (len == -1) {
pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER);
fprintf(stderr, "Sending Abort!\n");
} else if (service_data->segmented_message) {
pdu_len += abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
fprintf(stderr,"Sending Write Property Simple Ack!\n");
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED);
fprintf(stderr, "Sending Abort!\n");
} else {
switch (wp_data.object_type) {
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
pdu_len +=
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
fprintf(stderr, "Sending Write Property Simple Ack!\n");
} else {
pdu_len +=
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
fprintf(stderr, "Sending Write Property Error!\n");
}
break;
case OBJECT_ANALOG_INPUT:
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
pdu_len +=
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
fprintf(stderr, "Sending Write Access Error!\n");
break;
case OBJECT_ANALOG_OUTPUT:
if (Analog_Output_Write_Property(&wp_data, &error_class,
&error_code)) {
pdu_len +=
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
fprintf(stderr, "Sending Write Property Simple Ack!\n");
} else {
pdu_len +=
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
fprintf(stderr, "Sending Write Access Error!\n");
}
break;
default:
pdu_len +=
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
fprintf(stderr, "Sending Unknown Object Error!\n");
break;
}
else
{
pdu_len += bacerror_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class,
error_code);
fprintf(stderr,"Sending Write Property Error!\n");
}
break;
case OBJECT_ANALOG_INPUT:
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
pdu_len += bacerror_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class,
error_code);
fprintf(stderr,"Sending Write Access Error!\n");
break;
case OBJECT_ANALOG_OUTPUT:
if (Analog_Output_Write_Property(&wp_data,&error_class,&error_code))
{
pdu_len += encode_simple_ack(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
fprintf(stderr,"Sending Write Property Simple Ack!\n");
}
else
{
pdu_len += bacerror_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class,
error_code);
fprintf(stderr,"Sending Write Access Error!\n");
}
break;
default:
pdu_len += bacerror_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class,
error_code);
fprintf(stderr,"Sending Unknown Object Error!\n");
break;
}
}
bytes_sent = datalink_send_pdu(
src, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to send PDU (%s)!\n", strerror(errno));
bytes_sent = datalink_send_pdu(src, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr, "Failed to send PDU (%s)!\n", strerror(errno));
return;
return;
}
+47 -66
View File
@@ -37,83 +37,64 @@ extern bool I_Am_Request;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void handler_unrecognized_service(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *dest,
BACNET_CONFIRMED_SERVICE_DATA *service_data);
void handler_unrecognized_service(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * dest,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_who_is(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src);
void handler_who_has(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src);
void handler_who_is(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src);
void handler_i_am_add(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src);
void handler_i_am_bind(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src);
void handler_read_property(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_DATA *service_data);
void handler_who_has(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src);
void handler_read_property_ack(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_ACK_DATA *service_data);
void handler_i_am_add(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src);
void handler_write_property(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_DATA *service_data);
void handler_i_am_bind(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src);
void handler_atomic_read_file(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_DATA *service_data);
void handler_read_property(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_atomic_read_file_ack(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_ACK_DATA *service_data);
void handler_read_property_ack(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
void handler_reinitialize_device(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_DATA *service_data);
void handler_write_property(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_device_communication_control(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_DATA *service_data);
void handler_atomic_read_file(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_i_have(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src);
void handler_atomic_read_file_ack(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
void handler_reinitialize_device(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_device_communication_control(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_i_have(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+23 -33
View File
@@ -34,40 +34,30 @@
#include "npdu.h"
#include "reject.h"
void handler_unrecognized_service(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *dest,
BACNET_CONFIRMED_SERVICE_DATA *service_data)
void handler_unrecognized_service(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * dest, BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_ADDRESS src;
int pdu_len = 0;
int bytes_sent = 0;
(void)service_request;
(void)service_len;
datalink_get_my_address(&src);
BACNET_ADDRESS src;
int pdu_len = 0;
int bytes_sent = 0;
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
dest,
&src,
false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// encode the APDU portion of the packet
pdu_len += reject_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
REJECT_REASON_UNRECOGNIZED_SERVICE);
(void) service_request;
(void) service_len;
datalink_get_my_address(&src);
bytes_sent = datalink_send_pdu(
dest, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent > 0)
fprintf(stderr,"Sent Reject!\n");
else
fprintf(stderr,"Failed to Send Reject (%s)!\n", strerror(errno));
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], dest, &src, false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// encode the APDU portion of the packet
pdu_len += reject_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, REJECT_REASON_UNRECOGNIZED_SERVICE);
bytes_sent = datalink_send_pdu(dest, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent > 0)
fprintf(stderr, "Sent Reject!\n");
else
fprintf(stderr, "Failed to Send Reject (%s)!\n", strerror(errno));
}
+48 -65
View File
@@ -41,73 +41,56 @@
#include "handlers.h"
#include "txbuf.h"
uint8_t Send_Device_Communication_Control_Request(
uint32_t device_id,
uint16_t timeDuration, /* 0=optional */
BACNET_COMMUNICATION_ENABLE_DISABLE state,
char *password) /* NULL=optional */
{
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_CHARACTER_STRING password_string;
uint8_t Send_Device_Communication_Control_Request(uint32_t device_id, uint16_t timeDuration, /* 0=optional */
BACNET_COMMUNICATION_ENABLE_DISABLE state, char *password)
{ /* NULL=optional */
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_CHARACTER_STRING password_string;
if (!dcc_communication_enabled())
return 0;
if (!dcc_communication_enabled())
return 0;
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
status = tsm_transaction_available();
if (status)
{
datalink_get_my_address(&my_address);
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
&dest,
&my_address,
true, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
status = tsm_transaction_available();
if (status) {
datalink_get_my_address(&my_address);
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, &my_address, true, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
invoke_id = tsm_next_free_invokeID();
// load the data for the encoding
characterstring_init_ansi(&password_string,password);
pdu_len += dcc_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
invoke_id,
timeDuration,
state,
password?&password_string:NULL);
/* will it fit in the sender?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned)pdu_len < max_apdu)
{
tsm_set_confirmed_unsegmented_transaction(
invoke_id,
&dest,
&Handler_Transmit_Buffer[0],
pdu_len);
bytes_sent = datalink_send_pdu(
&dest, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to Send DeviceCommunicationControl Request (%s)!\n",
strerror(errno));
invoke_id = tsm_next_free_invokeID();
// load the data for the encoding
characterstring_init_ansi(&password_string, password);
pdu_len += dcc_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
invoke_id,
timeDuration, state, password ? &password_string : NULL);
/* will it fit in the sender?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned) pdu_len < max_apdu) {
tsm_set_confirmed_unsegmented_transaction(invoke_id,
&dest, &Handler_Transmit_Buffer[0], pdu_len);
bytes_sent = datalink_send_pdu(&dest, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,
"Failed to Send DeviceCommunicationControl Request (%s)!\n",
strerror(errno));
} else
fprintf(stderr,
"Failed to Send DeviceCommunicationControl Request "
"(exceeds destination maximum APDU)!\n");
}
else
fprintf(stderr,"Failed to Send DeviceCommunicationControl Request "
"(exceeds destination maximum APDU)!\n");
}
return invoke_id;
}
return invoke_id;
}
+28 -37
View File
@@ -43,43 +43,34 @@
#include "txbuf.h"
/* find a specific device, or use -1 for limit if you want unlimited */
void Send_I_Have(
uint32_t device_id,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
char *object_name)
void Send_I_Have(uint32_t device_id,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance, char *object_name)
{
int pdu_len = 0;
BACNET_ADDRESS dest;
int bytes_sent = 0;
BACNET_I_HAVE_DATA data;
int pdu_len = 0;
BACNET_ADDRESS dest;
int bytes_sent = 0;
BACNET_I_HAVE_DATA data;
/* if we are forbidden to send, don't send! */
if (!dcc_communication_enabled())
return;
/* Who-Has is a global broadcast */
datalink_get_broadcast_address(&dest);
/* encode the NPDU portion of the packet */
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
&dest,
NULL,
false, /* true for confirmed messages */
MESSAGE_PRIORITY_NORMAL);
/* encode the APDU portion of the packet */
data.device_id.type = OBJECT_DEVICE;
data.device_id.instance = device_id;
data.object_id.type = object_type;
data.object_id.instance = object_instance;
characterstring_init_ansi(&data.object_name,object_name);
pdu_len += ihave_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
&data);
/* send the data */
bytes_sent = datalink_send_pdu(
&dest, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to Send I-Have Reply (%s)!\n", strerror(errno));
/* if we are forbidden to send, don't send! */
if (!dcc_communication_enabled())
return;
/* Who-Has is a global broadcast */
datalink_get_broadcast_address(&dest);
/* encode the NPDU portion of the packet */
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, /* true for confirmed messages */
MESSAGE_PRIORITY_NORMAL);
/* encode the APDU portion of the packet */
data.device_id.type = OBJECT_DEVICE;
data.device_id.instance = device_id;
data.object_id.type = object_type;
data.object_id.instance = object_instance;
characterstring_init_ansi(&data.object_name, object_name);
pdu_len += ihave_encode_apdu(&Handler_Transmit_Buffer[pdu_len], &data);
/* send the data */
bytes_sent = datalink_send_pdu(&dest, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr, "Failed to Send I-Have Reply (%s)!\n",
strerror(errno));
}
+45 -62
View File
@@ -42,71 +42,54 @@
#include "handlers.h"
#include "txbuf.h"
uint8_t Send_Reinitialize_Device_Request(
uint32_t device_id,
BACNET_REINITIALIZED_STATE state,
char *password)
uint8_t Send_Reinitialize_Device_Request(uint32_t device_id,
BACNET_REINITIALIZED_STATE state, char *password)
{
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_CHARACTER_STRING password_string;
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_CHARACTER_STRING password_string;
if (!dcc_communication_enabled())
return 0;
if (!dcc_communication_enabled())
return 0;
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
status = tsm_transaction_available();
if (status)
{
datalink_get_my_address(&my_address);
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
&dest,
&my_address,
true, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
status = tsm_transaction_available();
if (status) {
datalink_get_my_address(&my_address);
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, &my_address, true, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
invoke_id = tsm_next_free_invokeID();
// load the data for the encoding
characterstring_init_ansi(&password_string,password);
pdu_len += rd_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
invoke_id,
state,
password?&password_string:NULL);
/* will it fit in the sender?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned)pdu_len < max_apdu)
{
tsm_set_confirmed_unsegmented_transaction(
invoke_id,
&dest,
&Handler_Transmit_Buffer[0],
pdu_len);
bytes_sent = datalink_send_pdu(
&dest, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to Send ReinitializeDevice Request (%s)!\n",
strerror(errno));
invoke_id = tsm_next_free_invokeID();
// load the data for the encoding
characterstring_init_ansi(&password_string, password);
pdu_len += rd_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
invoke_id, state, password ? &password_string : NULL);
/* will it fit in the sender?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned) pdu_len < max_apdu) {
tsm_set_confirmed_unsegmented_transaction(invoke_id,
&dest, &Handler_Transmit_Buffer[0], pdu_len);
bytes_sent = datalink_send_pdu(&dest, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,
"Failed to Send ReinitializeDevice Request (%s)!\n",
strerror(errno));
} else
fprintf(stderr, "Failed to Send ReinitializeDevice Request "
"(exceeds destination maximum APDU)!\n");
}
else
fprintf(stderr,"Failed to Send ReinitializeDevice Request "
"(exceeds destination maximum APDU)!\n");
}
return invoke_id;
}
return invoke_id;
}
+49 -64
View File
@@ -43,74 +43,59 @@
#include "txbuf.h"
/* returns invoke id of 0 if device is not bound or no tsm available */
uint8_t Send_Read_Property_Request(
uint32_t device_id, /* destination device */
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID object_property,
int32_t array_index)
uint8_t Send_Read_Property_Request(uint32_t device_id, /* destination device */
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID object_property, int32_t array_index)
{
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_READ_PROPERTY_DATA data;
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_READ_PROPERTY_DATA data;
if (!dcc_communication_enabled())
return 0;
if (!dcc_communication_enabled())
return 0;
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
status = tsm_transaction_available();
if (status)
{
datalink_get_my_address(&my_address);
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
&dest,
&my_address,
true, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
status = tsm_transaction_available();
if (status) {
datalink_get_my_address(&my_address);
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, &my_address, true, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
invoke_id = tsm_next_free_invokeID();
// load the data for the encoding
data.object_type = object_type;
data.object_instance = object_instance;
data.object_property = object_property;
data.array_index = array_index;
pdu_len += rp_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
invoke_id,
&data);
/* will it fit in the sender?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned)pdu_len < max_apdu)
{
tsm_set_confirmed_unsegmented_transaction(
invoke_id,
&dest,
&Handler_Transmit_Buffer[0],
pdu_len);
bytes_sent = datalink_send_pdu(
&dest, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to Send ReadProperty Request (%s)!\n",
strerror(errno));
invoke_id = tsm_next_free_invokeID();
// load the data for the encoding
data.object_type = object_type;
data.object_instance = object_instance;
data.object_property = object_property;
data.array_index = array_index;
pdu_len += rp_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
invoke_id, &data);
/* will it fit in the sender?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned) pdu_len < max_apdu) {
tsm_set_confirmed_unsegmented_transaction(invoke_id,
&dest, &Handler_Transmit_Buffer[0], pdu_len);
bytes_sent = datalink_send_pdu(&dest, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,
"Failed to Send ReadProperty Request (%s)!\n",
strerror(errno));
} else
fprintf(stderr, "Failed to Send ReadProperty Request "
"(exceeds destination maximum APDU)!\n");
}
else
fprintf(stderr,"Failed to Send ReadProperty Request "
"(exceeds destination maximum APDU)!\n");
}
return invoke_id;
return invoke_id;
}
+56 -72
View File
@@ -43,83 +43,67 @@
#include "txbuf.h"
/* find a specific device, or use -1 for limit if you want unlimited */
void Send_WhoHas_Name(
int32_t low_limit,
int32_t high_limit,
char *object_name)
void Send_WhoHas_Name(int32_t low_limit,
int32_t high_limit, char *object_name)
{
int pdu_len = 0;
BACNET_ADDRESS dest;
int bytes_sent = 0;
BACNET_WHO_HAS_DATA data;
int pdu_len = 0;
BACNET_ADDRESS dest;
int bytes_sent = 0;
BACNET_WHO_HAS_DATA data;
/* if we are forbidden to send, don't send! */
if (!dcc_communication_enabled())
return;
/* Who-Has is a global broadcast */
datalink_get_broadcast_address(&dest);
/* encode the NPDU portion of the packet */
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
&dest,
NULL,
false, /* true for confirmed messages */
MESSAGE_PRIORITY_NORMAL);
/* encode the APDU portion of the packet */
data.low_limit = low_limit;
data.high_limit = high_limit;
data.object_name = true;
characterstring_init_ansi(&data.object.name,object_name);
pdu_len += whohas_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
&data);
/* send the data */
bytes_sent = datalink_send_pdu(
&dest, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to Send Who-Has Request (%s)!\n", strerror(errno));
/* if we are forbidden to send, don't send! */
if (!dcc_communication_enabled())
return;
/* Who-Has is a global broadcast */
datalink_get_broadcast_address(&dest);
/* encode the NPDU portion of the packet */
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, /* true for confirmed messages */
MESSAGE_PRIORITY_NORMAL);
/* encode the APDU portion of the packet */
data.low_limit = low_limit;
data.high_limit = high_limit;
data.object_name = true;
characterstring_init_ansi(&data.object.name, object_name);
pdu_len += whohas_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
&data);
/* send the data */
bytes_sent = datalink_send_pdu(&dest, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr, "Failed to Send Who-Has Request (%s)!\n",
strerror(errno));
}
/* find a specific device, or use -1 for limit if you want unlimited */
void Send_WhoHas_Object(
int32_t low_limit,
int32_t high_limit,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance)
void Send_WhoHas_Object(int32_t low_limit,
int32_t high_limit,
BACNET_OBJECT_TYPE object_type, uint32_t object_instance)
{
int pdu_len = 0;
BACNET_ADDRESS dest;
int bytes_sent = 0;
BACNET_WHO_HAS_DATA data;
int pdu_len = 0;
BACNET_ADDRESS dest;
int bytes_sent = 0;
BACNET_WHO_HAS_DATA data;
/* if we are forbidden to send, don't send! */
if (!dcc_communication_enabled())
return;
/* Who-Has is a global broadcast */
datalink_get_broadcast_address(&dest);
/* encode the NPDU portion of the packet */
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
&dest,
NULL,
false, /* true for confirmed messages */
MESSAGE_PRIORITY_NORMAL);
/* encode the APDU portion of the packet */
data.low_limit = low_limit;
data.high_limit = high_limit;
data.object_name = false;
data.object.identifier.type = object_type;
data.object.identifier.instance = object_instance;
pdu_len += whohas_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
&data);
/* send the data */
bytes_sent = datalink_send_pdu(
&dest, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to Send Who-Has Request (%s)!\n", strerror(errno));
/* if we are forbidden to send, don't send! */
if (!dcc_communication_enabled())
return;
/* Who-Has is a global broadcast */
datalink_get_broadcast_address(&dest);
/* encode the NPDU portion of the packet */
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, /* true for confirmed messages */
MESSAGE_PRIORITY_NORMAL);
/* encode the APDU portion of the packet */
data.low_limit = low_limit;
data.high_limit = high_limit;
data.object_name = false;
data.object.identifier.type = object_type;
data.object.identifier.instance = object_instance;
pdu_len += whohas_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
&data);
/* send the data */
bytes_sent = datalink_send_pdu(&dest, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr, "Failed to Send Who-Has Request (%s)!\n",
strerror(errno));
}
+19 -28
View File
@@ -43,38 +43,29 @@
#include "txbuf.h"
/* find a specific device, or use -1 for limit if you want unlimited */
void Send_WhoIs(
int32_t low_limit,
int32_t high_limit)
void Send_WhoIs(int32_t low_limit, int32_t high_limit)
{
int pdu_len = 0;
BACNET_ADDRESS dest;
int bytes_sent = 0;
int pdu_len = 0;
BACNET_ADDRESS dest;
int bytes_sent = 0;
if (!dcc_communication_enabled())
return;
if (!dcc_communication_enabled())
return;
// Who-Is is a global broadcast
datalink_get_broadcast_address(&dest);
// Who-Is is a global broadcast
datalink_get_broadcast_address(&dest);
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
&dest,
NULL,
false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// encode the NPDU portion of the packet
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
// encode the APDU portion of the packet
pdu_len += whois_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
low_limit,
high_limit);
// encode the APDU portion of the packet
pdu_len += whois_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
low_limit, high_limit);
bytes_sent = datalink_send_pdu(
&dest, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to Send Who-Is Request (%s)!\n", strerror(errno));
bytes_sent = datalink_send_pdu(&dest, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr, "Failed to Send Who-Is Request (%s)!\n",
strerror(errno));
}
+53 -69
View File
@@ -43,79 +43,63 @@
#include "txbuf.h"
/* returns the invoke ID for confirmed request, or zero on failure */
uint8_t Send_Write_Property_Request(
uint32_t device_id, // destination device
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID object_property,
BACNET_APPLICATION_DATA_VALUE *object_value,
uint8_t priority,
int32_t array_index)
uint8_t Send_Write_Property_Request(uint32_t device_id, // destination device
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID object_property,
BACNET_APPLICATION_DATA_VALUE * object_value,
uint8_t priority, int32_t array_index)
{
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_WRITE_PROPERTY_DATA data;
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_WRITE_PROPERTY_DATA data;
if (!dcc_communication_enabled())
return 0;
if (!dcc_communication_enabled())
return 0;
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
status = tsm_transaction_available();
if (status)
{
datalink_get_my_address(&my_address);
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
&dest,
&my_address,
true, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
status = tsm_transaction_available();
if (status) {
datalink_get_my_address(&my_address);
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, &my_address, true, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
invoke_id = tsm_next_free_invokeID();
// load the data for the encoding
data.object_type = object_type;
data.object_instance = object_instance;
data.object_property = object_property;
data.array_index = array_index;
bacapp_copy(&data.value,object_value);
data.priority = priority;
pdu_len += wp_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
invoke_id,
&data);
/* will it fit in the sender?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned)pdu_len < max_apdu)
{
tsm_set_confirmed_unsegmented_transaction(
invoke_id,
&dest,
&Handler_Transmit_Buffer[0],
pdu_len);
bytes_sent = datalink_send_pdu(
&dest, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to Send WriteProperty Request (%s)!\n",
strerror(errno));
invoke_id = tsm_next_free_invokeID();
// load the data for the encoding
data.object_type = object_type;
data.object_instance = object_instance;
data.object_property = object_property;
data.array_index = array_index;
bacapp_copy(&data.value, object_value);
data.priority = priority;
pdu_len += wp_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
invoke_id, &data);
/* will it fit in the sender?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned) pdu_len < max_apdu) {
tsm_set_confirmed_unsegmented_transaction(invoke_id,
&dest, &Handler_Transmit_Buffer[0], pdu_len);
bytes_sent = datalink_send_pdu(&dest, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,
"Failed to Send WriteProperty Request (%s)!\n",
strerror(errno));
} else
fprintf(stderr, "Failed to Send WriteProperty Request "
"(exceeds destination maximum APDU)!\n");
}
else
fprintf(stderr,"Failed to Send WriteProperty Request "
"(exceeds destination maximum APDU)!\n");
}
return invoke_id;
return invoke_id;
}
+1 -2
View File
@@ -27,5 +27,4 @@
#include "config.h"
#include "datalink.h"
uint8_t Handler_Transmit_Buffer[MAX_MPDU] = {0};
uint8_t Handler_Transmit_Buffer[MAX_MPDU] = { 0 };
+76 -85
View File
@@ -31,7 +31,7 @@
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h" // the custom stuff
#include "config.h" // the custom stuff
#define MAX_ANALOG_INPUTS 7
@@ -40,17 +40,17 @@
// given instance exists
bool Analog_Input_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_ANALOG_INPUTS)
return true;
if (object_instance < MAX_ANALOG_INPUTS)
return true;
return false;
return false;
}
// we simply have 0-n object instances. Yours might be
// more complex, and then count how many you have
unsigned Analog_Input_Count(void)
{
return MAX_ANALOG_INPUTS;
return MAX_ANALOG_INPUTS;
}
// we simply have 0-n object instances. Yours might be
@@ -58,81 +58,77 @@ unsigned Analog_Input_Count(void)
// that correlates to the correct index
uint32_t Analog_Input_Index_To_Instance(unsigned index)
{
return index;
return index;
}
char *Analog_Input_Name(uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
if (object_instance < MAX_ANALOG_INPUTS)
{
sprintf(text_string,"ANALOG INPUT %u",object_instance);
return text_string;
}
static char text_string[32] = ""; /* okay for single thread */
return NULL;
if (object_instance < MAX_ANALOG_INPUTS) {
sprintf(text_string, "ANALOG INPUT %u", object_instance);
return text_string;
}
return NULL;
}
/* return apdu length, or -1 on error */
/* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(
uint8_t *apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; // return value
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
float value = 3.14;
(void)array_index;
switch (property)
{
int apdu_len = 0; // return value
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
float value = 3.14;
(void) array_index;
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
break;
apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string, Analog_Input_Name(object_instance));
apdu_len = encode_tagged_character_string(&apdu[0],
&char_string);
break;
characterstring_init_ansi(&char_string,
Analog_Input_Name(object_instance));
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_ANALOG_INPUT);
break;
apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_ANALOG_INPUT);
break;
case PROP_PRESENT_VALUE:
apdu_len = encode_tagged_real(&apdu[0], value);
break;
apdu_len = encode_tagged_real(&apdu[0], value);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_tagged_bitstring(&apdu[0], &bit_string);
break;
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_tagged_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len = encode_tagged_enumerated(&apdu[0],EVENT_STATE_NORMAL);
break;
apdu_len = encode_tagged_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_tagged_boolean(&apdu[0],false);
break;
apdu_len = encode_tagged_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_tagged_enumerated(&apdu[0],UNITS_PERCENT);
break;
apdu_len = encode_tagged_enumerated(&apdu[0], UNITS_PERCENT);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
return apdu_len;
}
#ifdef TEST
@@ -142,34 +138,31 @@ int Analog_Input_Encode_Property_APDU(
void testAnalogInput(Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_OUTPUT;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_OUTPUT;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
// FIXME: we should do a lot more testing here...
len = Analog_Input_Encode_Property_APDU(
&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL,
&error_class,
&error_code);
ct_test(pTest, len >= 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len = decode_object_id(&apdu[len],
// FIXME: we should do a lot more testing here...
len = Analog_Input_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len >= 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len = decode_object_id(&apdu[len],
(int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_ANALOG_INPUT);
ct_test(pTest, decoded_instance == instance);
ct_test(pTest, decoded_type == OBJECT_ANALOG_INPUT);
ct_test(pTest, decoded_instance == instance);
return;
return;
}
#ifdef TEST_ANALOG_INPUT
@@ -192,5 +185,3 @@ int main(void)
}
#endif /* TEST_ANALOG_INPUT */
#endif /* TEST */
+12 -15
View File
@@ -31,28 +31,25 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
bool Analog_Input_Valid_Instance(uint32_t object_instance);
unsigned Analog_Input_Count(void);
uint32_t Analog_Input_Index_To_Instance(unsigned index);
char *Analog_Input_Name(uint32_t object_instance);
bool Analog_Input_Valid_Instance(uint32_t object_instance);
unsigned Analog_Input_Count(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,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code);
int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
#ifdef TEST
#include "ctest.h"
void testAnalogInput(Test * pTest);
void testAnalogInput(Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+239 -277
View File
@@ -31,7 +31,7 @@
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h" // the custom stuff
#include "config.h" // the custom stuff
#include "wp.h"
#define MAX_ANALOG_OUTPUTS 4
@@ -46,7 +46,8 @@
// Here is our Priority Array. They are supposed to be Real, but
// we don't have that kind of memory, so we will use a single byte
// and load a Real for returning the value when asked.
static uint8_t Analog_Output_Level[MAX_ANALOG_OUTPUTS][BACNET_MAX_PRIORITY];
static uint8_t
Analog_Output_Level[MAX_ANALOG_OUTPUTS][BACNET_MAX_PRIORITY];
// Writable out-of-service allows others to play with our Present Value
// without changing the physical output
static bool Analog_Output_Out_Of_Service[MAX_ANALOG_OUTPUTS];
@@ -56,23 +57,20 @@ static bool Analog_Ouput_Initialized = false;
void Analog_Output_Init(void)
{
unsigned i,j;
unsigned i, j;
if (!Analog_Ouput_Initialized)
{
Analog_Ouput_Initialized = true;
// initialize all the analog output priority arrays to NULL
for (i = 0; i < MAX_ANALOG_OUTPUTS; i++)
{
for (j = 0; j < BACNET_MAX_PRIORITY; j++)
{
Analog_Output_Level[i][j] = AO_LEVEL_NULL;
}
if (!Analog_Ouput_Initialized) {
Analog_Ouput_Initialized = true;
// initialize all the analog output priority arrays to NULL
for (i = 0; i < MAX_ANALOG_OUTPUTS; i++) {
for (j = 0; j < BACNET_MAX_PRIORITY; j++) {
Analog_Output_Level[i][j] = AO_LEVEL_NULL;
}
}
}
}
return;
return;
}
// we simply have 0-n object instances. Yours might be
@@ -80,19 +78,19 @@ void Analog_Output_Init(void)
// given instance exists
bool Analog_Output_Valid_Instance(uint32_t object_instance)
{
Analog_Output_Init();
if (object_instance < MAX_ANALOG_OUTPUTS)
return true;
Analog_Output_Init();
if (object_instance < MAX_ANALOG_OUTPUTS)
return true;
return false;
return false;
}
// we simply have 0-n object instances. Yours might be
// more complex, and then count how many you have
unsigned Analog_Output_Count(void)
{
Analog_Output_Init();
return MAX_ANALOG_OUTPUTS;
Analog_Output_Init();
return MAX_ANALOG_OUTPUTS;
}
// we simply have 0-n object instances. Yours might be
@@ -100,8 +98,8 @@ unsigned Analog_Output_Count(void)
// that correlates to the correct index
uint32_t Analog_Output_Index_To_Instance(unsigned index)
{
Analog_Output_Init();
return index;
Analog_Output_Init();
return index;
}
// we simply have 0-n object instances. Yours might be
@@ -109,271 +107,240 @@ uint32_t Analog_Output_Index_To_Instance(unsigned index)
// that correlates to the correct instance number
unsigned Analog_Output_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_ANALOG_OUTPUTS;
unsigned index = MAX_ANALOG_OUTPUTS;
Analog_Output_Init();
if (object_instance < MAX_ANALOG_OUTPUTS)
index = object_instance;
return index;
Analog_Output_Init();
if (object_instance < MAX_ANALOG_OUTPUTS)
index = object_instance;
return index;
}
static float Analog_Output_Present_Value(uint32_t object_instance)
{
float value = AO_RELINQUISH_DEFAULT;
unsigned index = 0;
unsigned i = 0;
float value = AO_RELINQUISH_DEFAULT;
unsigned index = 0;
unsigned i = 0;
Analog_Output_Init();
index = Analog_Output_Instance_To_Index(object_instance);
if (index < MAX_ANALOG_OUTPUTS)
{
for (i = 0; i < BACNET_MAX_PRIORITY; i++)
{
if (Analog_Output_Level[index][i] != AO_LEVEL_NULL)
{
value = Analog_Output_Level[index][i];
break;
}
Analog_Output_Init();
index = Analog_Output_Instance_To_Index(object_instance);
if (index < MAX_ANALOG_OUTPUTS) {
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
if (Analog_Output_Level[index][i] != AO_LEVEL_NULL) {
value = Analog_Output_Level[index][i];
break;
}
}
}
}
return value;
return value;
}
/* note: the object name must be unique within this device */
char *Analog_Output_Name(uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
if (object_instance < MAX_ANALOG_OUTPUTS)
{
sprintf(text_string,"ANALOG OUTPUT %u",object_instance);
return text_string;
}
static char text_string[32] = ""; /* okay for single thread */
return NULL;
if (object_instance < MAX_ANALOG_OUTPUTS) {
sprintf(text_string, "ANALOG OUTPUT %u", object_instance);
return text_string;
}
return NULL;
}
/* return apdu len, or -1 on error */
int Analog_Output_Encode_Property_APDU(
uint8_t *apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
int Analog_Output_Encode_Property_APDU(uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
{
int len = 0;
int apdu_len = 0; // return value
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
float real_value = 1.414;
unsigned object_index = 0;
unsigned i = 0;
Analog_Output_Init();
switch (property)
{
int len = 0;
int apdu_len = 0; // return value
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
float real_value = 1.414;
unsigned object_index = 0;
unsigned i = 0;
Analog_Output_Init();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_tagged_object_id(&apdu[0], OBJECT_ANALOG_OUTPUT,
object_instance);
break;
apdu_len = encode_tagged_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_tagged_character_string(&apdu[0],
&char_string);
break;
characterstring_init_ansi(&char_string,
Analog_Output_Name(object_instance));
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_ANALOG_OUTPUT);
break;
apdu_len =
encode_tagged_enumerated(&apdu[0], OBJECT_ANALOG_OUTPUT);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Output_Present_Value(object_instance);
apdu_len = encode_tagged_real(&apdu[0], real_value);
break;
real_value = Analog_Output_Present_Value(object_instance);
apdu_len = encode_tagged_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_tagged_bitstring(&apdu[0], &bit_string);
break;
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_tagged_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len = encode_tagged_enumerated(&apdu[0],EVENT_STATE_NORMAL);
break;
apdu_len = encode_tagged_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_tagged_boolean(&apdu[0],false);
break;
apdu_len = encode_tagged_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_tagged_enumerated(&apdu[0],UNITS_PERCENT);
break;
apdu_len = encode_tagged_enumerated(&apdu[0], UNITS_PERCENT);
break;
case PROP_PRIORITY_ARRAY:
// Array element zero is the number of elements in the array
if (array_index == BACNET_ARRAY_LENGTH_INDEX)
apdu_len = encode_tagged_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_tagged_null(&apdu[apdu_len]);
else
{
real_value = Analog_Output_Level[object_index][i];
len = encode_tagged_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;
}
// Array element zero is the number of elements in the array
if (array_index == BACNET_ARRAY_LENGTH_INDEX)
apdu_len =
encode_tagged_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_tagged_null(&apdu[apdu_len]);
else {
real_value = Analog_Output_Level[object_index][i];
len = encode_tagged_real(&apdu[apdu_len], real_value);
}
// add it if we have room
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index =
Analog_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Analog_Output_Level[object_index][array_index] ==
AO_LEVEL_NULL)
len = encode_tagged_null(&apdu[apdu_len]);
else {
real_value =
Analog_Output_Level[object_index][array_index];
len = encode_tagged_real(&apdu[apdu_len], real_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
}
else
{
object_index = Analog_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY)
{
if (Analog_Output_Level[object_index][array_index] == AO_LEVEL_NULL)
len = encode_tagged_null(&apdu[apdu_len]);
else
{
real_value = Analog_Output_Level[object_index][array_index];
len = encode_tagged_real(&apdu[apdu_len], real_value);
}
}
else
{
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
break;
case PROP_RELINQUISH_DEFAULT:
real_value = AO_RELINQUISH_DEFAULT;
apdu_len = encode_tagged_real(&apdu[0], real_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
break;
case PROP_RELINQUISH_DEFAULT:
real_value = AO_RELINQUISH_DEFAULT;
apdu_len = encode_tagged_real(&apdu[0], real_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
// returns true if successful
bool Analog_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA *wp_data,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
bool Analog_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
{
bool status = false; // return value
unsigned int object_index = 0;
unsigned int priority = 0;
uint8_t level = AO_LEVEL_NULL;
Analog_Output_Init();
if (!Analog_Output_Valid_Instance(wp_data->object_instance))
{
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
bool status = false; // return value
unsigned int object_index = 0;
unsigned int priority = 0;
uint8_t level = AO_LEVEL_NULL;
// decode the some of the request
switch (wp_data->object_property)
{
Analog_Output_Init();
if (!Analog_Output_Valid_Instance(wp_data->object_instance)) {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
// decode the some of the request
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (wp_data->value.tag == BACNET_APPLICATION_TAG_REAL)
{
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */) &&
(wp_data->value.type.Real >= 0.0) &&
(wp_data->value.type.Real <= 100.0))
{
level = (uint8_t)wp_data->value.type.Real;
object_index = Analog_Output_Instance_To_Index(
wp_data->object_instance);
priority--;
Analog_Output_Level[object_index][priority] = level;
// 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;
if (wp_data->value.tag == BACNET_APPLICATION_TAG_REAL) {
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(wp_data->value.type.Real >= 0.0) &&
(wp_data->value.type.Real <= 100.0)) {
level = (uint8_t) wp_data->value.type.Real;
object_index =
Analog_Output_Instance_To_Index(wp_data->
object_instance);
priority--;
Analog_Output_Level[object_index][priority] = level;
// 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) {
*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 (wp_data->value.tag == BACNET_APPLICATION_TAG_NULL) {
level = AO_LEVEL_NULL;
object_index =
Analog_Output_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Analog_Output_Level[object_index][priority] = level;
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;
}
else if (priority == 6)
{
*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 (wp_data->value.tag == BACNET_APPLICATION_TAG_NULL)
{
level = AO_LEVEL_NULL;
object_index = Analog_Output_Instance_To_Index(
wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY))
{
priority--;
Analog_Output_Level[object_index][priority] = level;
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;
break;
case PROP_OUT_OF_SERVICE:
if (wp_data->value.tag == BACNET_APPLICATION_TAG_BOOLEAN)
{
object_index = Analog_Output_Instance_To_Index(
wp_data->object_instance);
Analog_Output_Out_Of_Service[object_index] =
wp_data->value.type.Boolean;
status = true;
}
else
{
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
if (wp_data->value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Analog_Output_Instance_To_Index(wp_data->object_instance);
Analog_Output_Out_Of_Service[object_index] =
wp_data->value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
return status;
}
@@ -384,33 +351,30 @@ bool Analog_Output_Write_Property(
void testAnalogOutput(Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_OUTPUT;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_OUTPUT;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
len = Analog_Output_Encode_Property_APDU(
&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL,
&error_class,
&error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len = decode_object_id(&apdu[len],
len = Analog_Output_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len = decode_object_id(&apdu[len],
(int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_ANALOG_OUTPUT);
ct_test(pTest, decoded_instance == instance);
ct_test(pTest, decoded_type == OBJECT_ANALOG_OUTPUT);
ct_test(pTest, decoded_instance == instance);
return;
return;
}
#ifdef TEST_ANALOG_OUTPUT
@@ -433,5 +397,3 @@ int main(void)
}
#endif /* TEST_ANALOG_INPUT */
#endif /* TEST */
+14 -19
View File
@@ -33,33 +33,28 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
bool Analog_Output_Valid_Instance(uint32_t object_instance);
unsigned Analog_Output_Count(void);
uint32_t Analog_Output_Index_To_Instance(unsigned index);
char *Analog_Output_Name(uint32_t object_instance);
bool Analog_Output_Valid_Instance(uint32_t object_instance);
unsigned Analog_Output_Count(void);
uint32_t Analog_Output_Index_To_Instance(unsigned index);
char *Analog_Output_Name(uint32_t object_instance);
int Analog_Output_Encode_Property_APDU(
uint8_t *apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code);
int Analog_Output_Encode_Property_APDU(uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
bool Analog_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA *wp_data,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code);
bool Analog_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
#ifdef TEST
#include "ctest.h"
void testAnalogOutput(Test * pTest);
void testAnalogOutput(Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+198 -245
View File
@@ -39,207 +39,182 @@
#include "arf.h"
#include "awf.h"
typedef struct
{
uint32_t instance;
char *filename;
typedef struct {
uint32_t instance;
char *filename;
} BACNET_FILE_LISTING;
static BACNET_FILE_LISTING BACnet_File_Listing[] =
{
{0, "test.log"},
{1, "script.txt"},
{2, "bacenum.h"},
{0, NULL} // last file indication
static BACNET_FILE_LISTING BACnet_File_Listing[] = {
{0, "test.log"},
{1, "script.txt"},
{2, "bacenum.h"},
{0, NULL} // last file indication
};
char *bacfile_name(uint32_t instance)
{
uint32_t index = 0;
char *filename = NULL;
uint32_t index = 0;
char *filename = NULL;
// linear search for file instance match
while (BACnet_File_Listing[index].filename)
{
if (BACnet_File_Listing[index].instance == instance)
{
filename = BACnet_File_Listing[index].filename;
break;
// linear search for file instance match
while (BACnet_File_Listing[index].filename) {
if (BACnet_File_Listing[index].instance == instance) {
filename = BACnet_File_Listing[index].filename;
break;
}
index++;
}
index++;
}
return filename;
return filename;
}
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 index = 0;
uint32_t index = 0;
// linear search for file instance match
while (BACnet_File_Listing[index].filename)
{
index++;
}
// linear search for file instance match
while (BACnet_File_Listing[index].filename) {
index++;
}
return index;
return index;
}
uint32_t bacfile_index_to_instance(unsigned find_index)
{
uint32_t instance = BACNET_MAX_INSTANCE + 1;
uint32_t index = 0;
// bounds checking...
while (BACnet_File_Listing[index].filename)
{
if (index == find_index)
{
instance = BACnet_File_Listing[index].instance;
break;
}
index++;
}
uint32_t instance = BACNET_MAX_INSTANCE + 1;
uint32_t index = 0;
return instance;
// bounds checking...
while (BACnet_File_Listing[index].filename) {
if (index == find_index) {
instance = BACnet_File_Listing[index].instance;
break;
}
index++;
}
return instance;
}
static long fsize(FILE *pFile)
static long fsize(FILE * pFile)
{
long size = 0;
long origin = 0;
long size = 0;
long origin = 0;
if (pFile)
{
origin = ftell(pFile);
fseek(pFile, 0L, SEEK_END);
size = ftell(pFile);
fseek(pFile, origin, SEEK_SET);
}
return (size);
if (pFile) {
origin = ftell(pFile);
fseek(pFile, 0L, SEEK_END);
size = ftell(pFile);
fseek(pFile, origin, SEEK_SET);
}
return (size);
}
static unsigned bacfile_file_size(uint32_t object_instance)
{
char *pFilename = NULL;
FILE *pFile = NULL;
unsigned file_size = 0;
char *pFilename = NULL;
FILE *pFile = NULL;
unsigned file_size = 0;
pFilename = bacfile_name(object_instance);
if (pFilename)
{
pFile = fopen(pFilename,"rb");
if (pFile)
{
file_size = fsize(pFile);
fclose(pFile);
pFilename = bacfile_name(object_instance);
if (pFilename) {
pFile = fopen(pFilename, "rb");
if (pFile) {
file_size = fsize(pFile);
fclose(pFile);
}
}
}
return file_size;
return file_size;
}
/* return the number of bytes used, or -1 on error */
int bacfile_encode_property_apdu(
uint8_t *apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
int bacfile_encode_property_apdu(uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; // return value
char text_string[32] = {""};
BACNET_CHARACTER_STRING char_string;
(void)array_index;
switch (property)
{
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_tagged_object_id(&apdu[0],
OBJECT_FILE,
object_instance);
break;
case PROP_OBJECT_NAME:
sprintf(text_string,"FILE %d",object_instance);
characterstring_init_ansi(&char_string, text_string);
apdu_len = encode_tagged_character_string(&apdu[0],
&char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_FILE);
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string, bacfile_name(object_instance));
apdu_len = encode_tagged_character_string(&apdu[0],
&char_string);
break;
case PROP_FILE_TYPE:
characterstring_init_ansi(&char_string, "TEXT");
apdu_len = encode_tagged_character_string(&apdu[0],
&char_string);
break;
case PROP_FILE_SIZE:
apdu_len = encode_tagged_unsigned(&apdu[0],
bacfile_file_size(object_instance));
break;
case PROP_MODIFICATION_DATE:
// FIXME: get the actual value
apdu_len = encode_tagged_date(&apdu[0],
2005,
12,
25,
7 /* sunday */);
// FIXME: get the actual value
apdu_len += encode_tagged_time(&apdu[apdu_len],
12,
0,
0,
0);
break;
case PROP_ARCHIVE:
// FIXME: get the actual value: note it may be inverse...
apdu_len = encode_tagged_boolean(&apdu[0],true);
break;
case PROP_READ_ONLY:
// FIXME: get the actual value
apdu_len = encode_tagged_boolean(&apdu[0],true);
break;
case PROP_FILE_ACCESS_METHOD:
apdu_len = encode_tagged_enumerated(&apdu[0],FILE_STREAM_ACCESS);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
int apdu_len = 0; // return value
char text_string[32] = { "" };
BACNET_CHARACTER_STRING char_string;
return apdu_len;
(void) array_index;
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_tagged_object_id(&apdu[0],
OBJECT_FILE, object_instance);
break;
case PROP_OBJECT_NAME:
sprintf(text_string, "FILE %d", object_instance);
characterstring_init_ansi(&char_string, text_string);
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_FILE);
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
bacfile_name(object_instance));
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
break;
case PROP_FILE_TYPE:
characterstring_init_ansi(&char_string, "TEXT");
apdu_len = encode_tagged_character_string(&apdu[0], &char_string);
break;
case PROP_FILE_SIZE:
apdu_len = encode_tagged_unsigned(&apdu[0],
bacfile_file_size(object_instance));
break;
case PROP_MODIFICATION_DATE:
// FIXME: get the actual value
apdu_len = encode_tagged_date(&apdu[0],
2005, 12, 25, 7 /* sunday */ );
// FIXME: get the actual value
apdu_len += encode_tagged_time(&apdu[apdu_len], 12, 0, 0, 0);
break;
case PROP_ARCHIVE:
// FIXME: get the actual value: note it may be inverse...
apdu_len = encode_tagged_boolean(&apdu[0], true);
break;
case PROP_READ_ONLY:
// FIXME: get the actual value
apdu_len = encode_tagged_boolean(&apdu[0], true);
break;
case PROP_FILE_ACCESS_METHOD:
apdu_len = encode_tagged_enumerated(&apdu[0], FILE_STREAM_ACCESS);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
uint32_t bacfile_instance(char *filename)
{
uint32_t index = 0;
uint32_t instance = BACNET_MAX_INSTANCE + 1;
uint32_t index = 0;
uint32_t instance = BACNET_MAX_INSTANCE + 1;
// linear search for filename match
while (BACnet_File_Listing[index].filename)
{
if (strcmp(BACnet_File_Listing[index].filename,filename) == 0)
{
instance = BACnet_File_Listing[index].instance;
break;
// linear search for filename match
while (BACnet_File_Listing[index].filename) {
if (strcmp(BACnet_File_Listing[index].filename, filename) == 0) {
instance = BACnet_File_Listing[index].instance;
break;
}
index++;
}
index++;
}
return instance;
return instance;
}
#if TSM_ENABLED
@@ -248,102 +223,80 @@ uint32_t bacfile_instance(char *filename)
// Another way would be to store the
// invokeID and file instance in a list or table
// when the request was sent
uint32_t bacfile_instance_from_tsm(
uint8_t invokeID)
uint32_t bacfile_instance_from_tsm(uint8_t invokeID)
{
BACNET_NPDU_DATA npdu_data = {0}; // dummy for getting npdu length
BACNET_CONFIRMED_SERVICE_DATA service_data = {0};
uint8_t service_choice = 0;
uint8_t *service_request = NULL;
uint16_t service_request_len = 0;
BACNET_ADDRESS dest; // where the original packet was destined
uint8_t pdu[MAX_PDU] = {0}; // original sent packet
uint16_t pdu_len = 0; // original packet length
uint16_t len = 0; // apdu header length
BACNET_ATOMIC_READ_FILE_DATA data = {0};
uint32_t object_instance = BACNET_MAX_INSTANCE + 1; // return value
bool found = false;
int apdu_offset = 0;
found = tsm_get_transaction_pdu(
invokeID,
&dest,
&pdu[0],
&pdu_len);
if (found)
{
apdu_offset = npdu_decode(
&pdu[0], // data to decode
NULL, // destination address - get the DNET/DLEN/DADR if in there
NULL, // source address - get the SNET/SLEN/SADR if in there
&npdu_data); // amount of data to decode
if (!npdu_data.network_layer_message &&
((pdu[apdu_offset] & 0xF0) == PDU_TYPE_CONFIRMED_SERVICE_REQUEST))
{
len = apdu_decode_confirmed_service_request(
&pdu[apdu_offset], // APDU data
pdu_len - apdu_offset,
&service_data,
&service_choice,
&service_request,
&service_request_len);
if (service_choice == SERVICE_CONFIRMED_ATOMIC_READ_FILE)
{
len = arf_decode_service_request(
service_request,
service_request_len,
&data);
if (len > 0)
{
if (data.object_type == OBJECT_FILE)
object_instance = data.object_instance;
BACNET_NPDU_DATA npdu_data = { 0 }; // dummy for getting npdu length
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
uint8_t service_choice = 0;
uint8_t *service_request = NULL;
uint16_t service_request_len = 0;
BACNET_ADDRESS dest; // where the original packet was destined
uint8_t pdu[MAX_PDU] = { 0 }; // original sent packet
uint16_t pdu_len = 0; // original packet length
uint16_t len = 0; // apdu header length
BACNET_ATOMIC_READ_FILE_DATA data = { 0 };
uint32_t object_instance = BACNET_MAX_INSTANCE + 1; // return value
bool found = false;
int apdu_offset = 0;
found = tsm_get_transaction_pdu(invokeID, &dest, &pdu[0], &pdu_len);
if (found) {
apdu_offset = npdu_decode(&pdu[0], // data to decode
NULL, // destination address - get the DNET/DLEN/DADR if in there
NULL, // source address - get the SNET/SLEN/SADR if in there
&npdu_data); // amount of data to decode
if (!npdu_data.network_layer_message &&
((pdu[apdu_offset] & 0xF0) ==
PDU_TYPE_CONFIRMED_SERVICE_REQUEST)) {
len = apdu_decode_confirmed_service_request(&pdu[apdu_offset], // APDU data
pdu_len - apdu_offset,
&service_data,
&service_choice, &service_request, &service_request_len);
if (service_choice == SERVICE_CONFIRMED_ATOMIC_READ_FILE) {
len = arf_decode_service_request(service_request,
service_request_len, &data);
if (len > 0) {
if (data.object_type == OBJECT_FILE)
object_instance = data.object_instance;
}
}
}
}
}
}
return object_instance;
return object_instance;
}
#endif
bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA *data)
bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA * data)
{
char *pFilename = NULL;
bool found = false;
FILE *pFile = NULL;
size_t len = 0;
pFilename = bacfile_name(data->object_instance);
if (pFilename)
{
found = true;
pFile = fopen(pFilename,"rb");
if (pFile)
{
(void)fseek(pFile,
data->type.stream.fileStartPosition,
SEEK_SET);
len = fread(octetstring_value(&data->fileData), 1,
data->type.stream.requestedOctetCount, pFile);
if (len < data->type.stream.requestedOctetCount)
data->endOfFile = true;
else
data->endOfFile = false;
octetstring_truncate(&data->fileData,len);
fclose(pFile);
}
else
{
octetstring_truncate(&data->fileData,0);
data->endOfFile = true;
}
}
else
{
octetstring_truncate(&data->fileData,0);
data->endOfFile = true;
}
char *pFilename = NULL;
bool found = false;
FILE *pFile = NULL;
size_t len = 0;
return found;
pFilename = bacfile_name(data->object_instance);
if (pFilename) {
found = true;
pFile = fopen(pFilename, "rb");
if (pFile) {
(void) fseek(pFile,
data->type.stream.fileStartPosition, SEEK_SET);
len = fread(octetstring_value(&data->fileData), 1,
data->type.stream.requestedOctetCount, pFile);
if (len < data->type.stream.requestedOctetCount)
data->endOfFile = true;
else
data->endOfFile = false;
octetstring_truncate(&data->fileData, len);
fclose(pFile);
} else {
octetstring_truncate(&data->fileData, 0);
data->endOfFile = true;
}
} else {
octetstring_truncate(&data->fileData, 0);
data->endOfFile = true;
}
return found;
}
+14 -18
View File
@@ -43,37 +43,33 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
char *bacfile_name(uint32_t instance);
bool bacfile_valid_instance(uint32_t object_instance);
uint32_t bacfile_count(void);
uint32_t bacfile_index_to_instance(unsigned find_index);
uint32_t bacfile_instance(char *filename);
char *bacfile_name(uint32_t instance);
bool bacfile_valid_instance(uint32_t object_instance);
uint32_t bacfile_count(void);
uint32_t bacfile_index_to_instance(unsigned find_index);
uint32_t bacfile_instance(char *filename);
#if TSM_ENABLED
// this is one way to match up the invoke ID with
// the file ID from the AtomicReadFile request.
// Another way would be to store the
// invokeID and file instance in a list or table
// when the request was sent
uint32_t bacfile_instance_from_tsm(
uint8_t invokeID);
uint32_t bacfile_instance_from_tsm(uint8_t invokeID);
#endif
// AtomicReadFile ACK helper
bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA *data);
bool bacfile_read_data(BACNET_ATOMIC_READ_FILE_DATA * data);
// handling for read property service
int bacfile_encode_property_apdu(
uint8_t *apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code);
int bacfile_encode_property_apdu(uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
File diff suppressed because it is too large Load Diff
+45 -54
View File
@@ -42,78 +42,69 @@
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
uint32_t Device_Object_Instance_Number(void);
bool Device_Set_Object_Instance_Number(uint32_t object_id);
bool Device_Valid_Object_Instance_Number(uint32_t object_id);
unsigned Device_Object_List_Count(void);
bool Device_Object_List_Identifier(unsigned array_index,
int *object_type,
uint32_t *instance);
uint32_t Device_Object_Instance_Number(void);
bool Device_Set_Object_Instance_Number(uint32_t object_id);
bool Device_Valid_Object_Instance_Number(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);
void Device_Set_System_Status(BACNET_DEVICE_STATUS status);
BACNET_DEVICE_STATUS Device_System_Status(void);
void Device_Set_System_Status(BACNET_DEVICE_STATUS status);
const char *Device_Vendor_Name(void);
bool Device_Set_Vendor_Name(const char *name, size_t length);
const char *Device_Vendor_Name(void);
bool Device_Set_Vendor_Name(const char *name, size_t length);
uint16_t Device_Vendor_Identifier(void);
void Device_Set_Vendor_Identifier(uint16_t vendor_id);
uint16_t Device_Vendor_Identifier(void);
void Device_Set_Vendor_Identifier(uint16_t vendor_id);
const char *Device_Model_Name(void);
bool Device_Set_Model_Name(const char *name, size_t length);
const char *Device_Model_Name(void);
bool Device_Set_Model_Name(const char *name, size_t length);
const char *Device_Firmware_Revision(void);
bool Device_Set_Firmware_Revision(const char *name, size_t length);
const char *Device_Firmware_Revision(void);
bool Device_Set_Firmware_Revision(const char *name, size_t length);
const char *Device_Application_Software_Version(void);
bool Device_Set_Application_Software_Version(const char *name, size_t length);
const char *Device_Application_Software_Version(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_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);
const char *Device_Location(void);
bool Device_Set_Location(const char *name, size_t length);
// some stack-centric constant values - no set methods
uint8_t Device_Protocol_Version(void);
uint8_t Device_Protocol_Revision(void);
uint16_t Device_Max_APDU_Length_Accepted(void);
BACNET_SEGMENTATION Device_Segmentation_Supported(void);
uint8_t Device_Protocol_Version(void);
uint8_t Device_Protocol_Revision(void);
uint16_t Device_Max_APDU_Length_Accepted(void);
BACNET_SEGMENTATION Device_Segmentation_Supported(void);
uint16_t Device_APDU_Timeout(void);
void Device_Set_APDU_Timeout(uint16_t timeout);
uint16_t Device_APDU_Timeout(void);
void Device_Set_APDU_Timeout(uint16_t timeout);
uint8_t Device_Number_Of_APDU_Retries(void);
void Device_Set_Number_Of_APDU_Retries(uint8_t retries);
uint8_t Device_Number_Of_APDU_Retries(void);
void Device_Set_Number_Of_APDU_Retries(uint8_t retries);
uint8_t Device_Database_Revision(void);
void Device_Set_Database_Revision(uint8_t revision);
uint8_t Device_Database_Revision(void);
void Device_Set_Database_Revision(uint8_t revision);
bool Device_Valid_Object_Name(
const char *object_name,
int *object_type,
uint32_t *object_instance);
char *Device_Valid_Object_Id(
int object_type,
uint32_t object_instance);
bool Device_Valid_Object_Name(const char *object_name,
int *object_type, uint32_t * object_instance);
char *Device_Valid_Object_Id(int object_type,
uint32_t object_instance);
int Device_Encode_Property_APDU(
uint8_t *apdu,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code);
int Device_Encode_Property_APDU(uint8_t * apdu,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
bool Device_Write_Property(
BACNET_WRITE_PROPERTY_DATA *wp_data,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code);
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+275 -350
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -49,7 +49,7 @@
#include "txbuf.h"
// buffer used for receive
static uint8_t Rx_Buf[MAX_MPDU] = {0};
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* global variables used in this file */
static uint32_t Target_File_Object_Instance = BACNET_MAX_INSTANCE;
@@ -60,397 +60,322 @@ static bool End_Of_File_Detected = false;
static bool Error_Detected = false;
static uint8_t Current_Invoke_ID = 0;
static void Atomic_Read_File_Error_Handler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
static void Atomic_Read_File_Error_Handler(BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("\r\nBACnet Error!\r\n");
printf("Error Class: %s\r\n",
bactext_error_class_name(error_class));
printf("Error Code: %s\r\n",
bactext_error_code_name(error_code));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("\r\nBACnet Error!\r\n");
printf("Error Class: %s\r\n", bactext_error_class_name(error_class));
printf("Error Code: %s\r\n", bactext_error_code_name(error_code));
Error_Detected = true;
}
void MyAbortHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
uint8_t abort_reason)
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("\r\nBACnet Abort!\r\n");
printf("Abort Reason: %s\r\n",
bactext_abort_reason_name(abort_reason));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("\r\nBACnet Abort!\r\n");
printf("Abort Reason: %s\r\n",
bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
uint8_t reject_reason)
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("\r\nBACnet Reject!\r\n");
printf("Reject Reason: %s\r\n",
bactext_reject_reason_name(reject_reason));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("\r\nBACnet Reject!\r\n");
printf("Reject Reason: %s\r\n",
bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
static uint8_t Send_Atomic_Read_File_Stream(
uint32_t device_id,
uint32_t file_instance,
int fileStartPosition,
unsigned requestedOctetCount)
static uint8_t Send_Atomic_Read_File_Stream(uint32_t device_id,
uint32_t file_instance,
int fileStartPosition, unsigned requestedOctetCount)
{
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_ATOMIC_READ_FILE_DATA data;
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_ATOMIC_READ_FILE_DATA data;
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
status = tsm_transaction_available();
if (status)
{
datalink_get_my_address(&my_address);
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
&dest,
&my_address,
true, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
status = tsm_transaction_available();
if (status) {
datalink_get_my_address(&my_address);
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, &my_address, true, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
invoke_id = tsm_next_free_invokeID();
// load the data for the encoding
data.object_type = OBJECT_FILE;
data.object_instance = file_instance;
data.access = FILE_STREAM_ACCESS;
data.type.stream.fileStartPosition = fileStartPosition;
data.type.stream.requestedOctetCount = requestedOctetCount;
pdu_len += arf_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
invoke_id,
&data);
/* will the APDU fit the target device?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned)pdu_len < max_apdu)
{
tsm_set_confirmed_unsegmented_transaction(
invoke_id,
&dest,
&Handler_Transmit_Buffer[0],
pdu_len);
bytes_sent = datalink_send_pdu(
&dest, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to Send AtomicReadFile Request (%s)!\n",
strerror(errno));
invoke_id = tsm_next_free_invokeID();
// load the data for the encoding
data.object_type = OBJECT_FILE;
data.object_instance = file_instance;
data.access = FILE_STREAM_ACCESS;
data.type.stream.fileStartPosition = fileStartPosition;
data.type.stream.requestedOctetCount = requestedOctetCount;
pdu_len += arf_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
invoke_id, &data);
/* will the APDU fit the target device?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned) pdu_len < max_apdu) {
tsm_set_confirmed_unsegmented_transaction(invoke_id,
&dest, &Handler_Transmit_Buffer[0], pdu_len);
bytes_sent = datalink_send_pdu(&dest, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,
"Failed to Send AtomicReadFile Request (%s)!\n",
strerror(errno));
} else
fprintf(stderr, "Failed to Send AtomicReadFile Request "
"(payload exceeds destination maximum APDU)!\n");
}
else
fprintf(stderr,"Failed to Send AtomicReadFile Request "
"(payload exceeds destination maximum APDU)!\n");
}
return invoke_id;
return invoke_id;
}
static void Send_WhoIs(uint32_t device_id)
{
int pdu_len = 0;
BACNET_ADDRESS dest;
int bytes_sent = 0;
int pdu_len = 0;
BACNET_ADDRESS dest;
int bytes_sent = 0;
/* Who-Is is a global broadcast */
datalink_get_broadcast_address(&dest);
/* Who-Is is a global broadcast */
datalink_get_broadcast_address(&dest);
/* encode the NPDU portion of the packet */
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
&dest,
NULL,
false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
/* encode the NPDU portion of the packet */
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
/* encode the APDU portion of the packet */
pdu_len += whois_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
device_id,
device_id);
/* encode the APDU portion of the packet */
pdu_len += whois_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
device_id, device_id);
bytes_sent = datalink_send_pdu(
&dest, /* destination address */
&Handler_Transmit_Buffer[0],
pdu_len); /* number of bytes of data */
if (bytes_sent <= 0)
fprintf(stderr,"Failed to Send Who-Is Request (%s)!\n", strerror(errno));
bytes_sent = datalink_send_pdu(&dest, /* destination address */
&Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */
if (bytes_sent <= 0)
fprintf(stderr, "Failed to Send Who-Is Request (%s)!\n",
strerror(errno));
}
static void AtomicReadFileAckHandler(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src,
BACNET_CONFIRMED_SERVICE_ACK_DATA *service_data)
static void AtomicReadFileAckHandler(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
{
int len = 0;
BACNET_ATOMIC_READ_FILE_DATA data;
FILE *pFile = NULL; /* stream pointer */
size_t octets_written = 0;
int len = 0;
BACNET_ATOMIC_READ_FILE_DATA data;
FILE *pFile = NULL; /* stream pointer */
size_t octets_written = 0;
(void)src; /* FIXME: validate the source address matches */
len = arf_ack_decode_service_request(
service_request,
service_len,
&data);
if (len > 0)
{
/* validate the parameters before storing data */
if ((data.access == FILE_STREAM_ACCESS) &&
(service_data->invoke_id == Current_Invoke_ID))
{
if (data.type.stream.fileStartPosition == 0)
pFile = fopen(Local_File_Name, "wb");
else
pFile = fopen(Local_File_Name, "rb+");
if (pFile)
{
/* is there anything to do with this? data.stream.requestedOctetCount */
(void)fseek(pFile, data.type.stream.fileStartPosition, SEEK_SET);
octets_written = fwrite(
octetstring_value(&data.fileData),
1, /* unit to write in bytes - in our case, an octet is one byte */
octetstring_length(&data.fileData),
pFile);
if (octets_written != octetstring_length(&data.fileData))
fprintf(stderr,"Unable to write data to file \"%s\".\n",
Local_File_Name);
else
printf("\r%u bytes",
(data.type.stream.fileStartPosition + octets_written));
fclose(pFile);
}
if (data.endOfFile)
{
End_Of_File_Detected = true;
printf("\r\n");
}
(void) src; /* FIXME: validate the source address matches */
len = arf_ack_decode_service_request(service_request,
service_len, &data);
if (len > 0) {
/* validate the parameters before storing data */
if ((data.access == FILE_STREAM_ACCESS) &&
(service_data->invoke_id == Current_Invoke_ID)) {
if (data.type.stream.fileStartPosition == 0)
pFile = fopen(Local_File_Name, "wb");
else
pFile = fopen(Local_File_Name, "rb+");
if (pFile) {
/* is there anything to do with this? data.stream.requestedOctetCount */
(void) fseek(pFile, data.type.stream.fileStartPosition,
SEEK_SET);
octets_written = fwrite(octetstring_value(&data.fileData), 1, /* unit to write in bytes - in our case, an octet is one byte */
octetstring_length(&data.fileData), pFile);
if (octets_written != octetstring_length(&data.fileData))
fprintf(stderr,
"Unable to write data to file \"%s\".\n",
Local_File_Name);
else
printf("\r%u bytes",
(data.type.stream.fileStartPosition +
octets_written));
fclose(pFile);
}
if (data.endOfFile) {
End_Of_File_Detected = true;
printf("\r\n");
}
}
}
}
}
static void LocalIAmHandler(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src)
static void LocalIAmHandler(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
{
int len = 0;
uint32_t device_id = 0;
unsigned max_apdu = 0;
int segmentation = 0;
uint16_t vendor_id = 0;
int len = 0;
uint32_t device_id = 0;
unsigned max_apdu = 0;
int segmentation = 0;
uint16_t vendor_id = 0;
(void)src;
(void)service_len;
len = iam_decode_service_request(
service_request,
&device_id,
&max_apdu,
&segmentation,
&vendor_id);
if (len != -1)
{
address_add(device_id,
max_apdu,
src);
}
else
fprintf(stderr,"!\n");
(void) src;
(void) service_len;
len = iam_decode_service_request(service_request,
&device_id, &max_apdu, &segmentation, &vendor_id);
if (len != -1) {
address_add(device_id, max_apdu, src);
} else
fprintf(stderr, "!\n");
return;
return;
}
static void Init_Service_Handlers(void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_I_AM,
LocalIAmHandler);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler(
handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the data coming back from confirmed requests */
apdu_set_confirmed_ack_handler(
SERVICE_CONFIRMED_ATOMIC_READ_FILE,
AtomicReadFileAckHandler);
/* handle any errors coming back */
apdu_set_error_handler(
SERVICE_CONFIRMED_ATOMIC_READ_FILE,
Atomic_Read_File_Error_Handler);
apdu_set_abort_handler(
MyAbortHandler);
apdu_set_reject_handler(
MyRejectHandler);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
LocalIAmHandler);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the data coming back from confirmed requests */
apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_ATOMIC_READ_FILE,
AtomicReadFileAckHandler);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_ATOMIC_READ_FILE,
Atomic_Read_File_Error_Handler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
int main(int argc, char *argv[])
{
BACNET_ADDRESS src = {0}; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
int fileStartPosition = 0;
unsigned requestedOctetCount = 0;
uint8_t invoke_id = 0;
bool found = false;
uint16_t my_max_apdu = 0;
if (argc < 4)
{
/* FIXME: what about access method - record or stream? */
printf("%s device-instance file-instance local-name\r\n",
filename_remove_path(argv[0]));
return 0;
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1],NULL,0);
Target_File_Object_Instance = strtol(argv[2],NULL,0);
Local_File_Name = argv[3];
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE)
{
fprintf(stderr,"device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance,BACNET_MAX_INSTANCE);
return 1;
}
if (Target_File_Object_Instance >= BACNET_MAX_INSTANCE)
{
fprintf(stderr,"file-instance=%u - it must be less than %u\r\n",
Target_File_Object_Instance,BACNET_MAX_INSTANCE+1);
return 1;
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
/* configure standard BACnet/IP port */
bip_set_interface("eth0"); /* for linux */
bip_set_port(0xBAC0);
if (!bip_init())
return 1;
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance);
/* loop forever */
for (;;)
{
/* increment timer - exit if timed out */
current_seconds = time(NULL);
BACNET_ADDRESS src = { 0 }; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
int fileStartPosition = 0;
unsigned requestedOctetCount = 0;
uint8_t invoke_id = 0;
bool found = false;
uint16_t my_max_apdu = 0;
/* returns 0 bytes on timeout */
pdu_len = bip_receive(
&src,
&Rx_Buf[0],
MAX_MPDU,
timeout);
/* process */
if (pdu_len)
{
npdu_handler(
&src,
&Rx_Buf[0],
pdu_len);
if (argc < 4) {
/* FIXME: what about access method - record or stream? */
printf("%s device-instance file-instance local-name\r\n",
filename_remove_path(argv[0]));
return 0;
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
if (End_Of_File_Detected || Error_Detected)
break;
if (I_Am_Request)
{
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
Target_File_Object_Instance = strtol(argv[2], NULL, 0);
Local_File_Name = argv[3];
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
else
{
/* wait until the device is bound, or timeout and quit */
found = address_bind_request(
Target_Device_Object_Instance,
&max_apdu,
&Target_Address);
if (found)
{
/* calculate the smaller of our APDU size or theirs
and remove the overhead of the APDU (about 16 octets max).
note: we could fail if there is a bottle neck (router)
and smaller MPDU in betweeen. */
if (max_apdu < MAX_APDU)
my_max_apdu = max_apdu;
else
my_max_apdu = MAX_APDU;
requestedOctetCount = my_max_apdu - 16;
/* has the previous invoke id expired or returned?
note: invoke ID = 0 is invalid, so it will be idle */
if ((invoke_id == 0) || tsm_invoke_id_free(invoke_id))
{
if (invoke_id != 0)
fileStartPosition += requestedOctetCount;
/* we'll read the file in chunks
less than max_apdu to keep unsegmented */
invoke_id = Send_Atomic_Read_File_Stream(
Target_Device_Object_Instance,
Target_File_Object_Instance,
fileStartPosition,
requestedOctetCount);
Current_Invoke_ID = invoke_id;
}
}
else
{
if (Target_File_Object_Instance >= BACNET_MAX_INSTANCE) {
fprintf(stderr, "file-instance=%u - it must be less than %u\r\n",
Target_File_Object_Instance, BACNET_MAX_INSTANCE + 1);
return 1;
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
/* configure standard BACnet/IP port */
bip_set_interface("eth0"); /* for linux */
bip_set_port(0xBAC0);
if (!bip_init())
return 1;
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance);
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds)
break;
}
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
current_seconds = time(NULL);
return 0;
/* returns 0 bytes on timeout */
pdu_len = bip_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds -
last_seconds) * 1000));
if (End_Of_File_Detected || Error_Detected)
break;
if (I_Am_Request) {
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
} else {
/* wait until the device is bound, or timeout and quit */
found = address_bind_request(Target_Device_Object_Instance,
&max_apdu, &Target_Address);
if (found) {
/* calculate the smaller of our APDU size or theirs
and remove the overhead of the APDU (about 16 octets max).
note: we could fail if there is a bottle neck (router)
and smaller MPDU in betweeen. */
if (max_apdu < MAX_APDU)
my_max_apdu = max_apdu;
else
my_max_apdu = MAX_APDU;
requestedOctetCount = my_max_apdu - 16;
/* has the previous invoke id expired or returned?
note: invoke ID = 0 is invalid, so it will be idle */
if ((invoke_id == 0) || tsm_invoke_id_free(invoke_id)) {
if (invoke_id != 0)
fileStartPosition += requestedOctetCount;
/* we'll read the file in chunks
less than max_apdu to keep unsegmented */
invoke_id =
Send_Atomic_Read_File_Stream
(Target_Device_Object_Instance,
Target_File_Object_Instance, fileStartPosition,
requestedOctetCount);
Current_Invoke_ID = invoke_id;
}
} else {
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds)
break;
}
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
return 0;
}
+154 -189
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -50,7 +50,7 @@
#include "txbuf.h"
// buffer used for receive
static uint8_t Rx_Buf[MAX_MPDU] = {0};
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* global variables used in this file */
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
@@ -62,211 +62,176 @@ static int32_t Target_Object_Index = BACNET_ARRAY_ALL;
static BACNET_ADDRESS Target_Address;
static bool Error_Detected = false;
static void MyErrorHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
static void MyErrorHandler(BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("BACnet Error: %s: %s\r\n",
bactext_error_class_name(error_class),
bactext_error_code_name(error_code));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Error: %s: %s\r\n",
bactext_error_class_name(error_class),
bactext_error_code_name(error_code));
Error_Detected = true;
}
void MyAbortHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
uint8_t abort_reason)
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name(abort_reason));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
uint8_t reject_reason)
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name(reject_reason));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
static void Init_Service_Handlers(void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_I_AM,
handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler(
handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the data coming back from confirmed requests */
apdu_set_confirmed_ack_handler(
SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property_ack);
/* handle any errors coming back */
apdu_set_error_handler(
SERVICE_CONFIRMED_READ_PROPERTY,
MyErrorHandler);
apdu_set_abort_handler(
MyAbortHandler);
apdu_set_reject_handler(
MyRejectHandler);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the data coming back from confirmed requests */
apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property_ack);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY,
MyErrorHandler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
int main(int argc, char *argv[])
{
BACNET_ADDRESS src = {0}; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
uint8_t invoke_id = 0;
bool found = false;
BACNET_ADDRESS src = { 0 }; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
uint8_t invoke_id = 0;
bool found = false;
if (argc < 5)
{
printf("%s device-instance object-type object-instance property [index]\r\n",
filename_remove_path(argv[0]));
return 0;
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1],NULL,0);
Target_Object_Type = strtol(argv[2],NULL,0);
Target_Object_Instance = strtol(argv[3],NULL,0);
Target_Object_Property = strtol(argv[4],NULL,0);
if (argc > 5)
Target_Object_Index = strtol(argv[5],NULL,0);
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE)
{
fprintf(stderr,"device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance,BACNET_MAX_INSTANCE);
return 1;
}
if (Target_Object_Type > MAX_BACNET_OBJECT_TYPE)
{
fprintf(stderr,"object-type=%u - it must be less than %u\r\n",
Target_Object_Type,MAX_BACNET_OBJECT_TYPE+1);
return 1;
}
if (Target_Object_Instance > BACNET_MAX_INSTANCE)
{
fprintf(stderr,"object-instance=%u - it must be less than %u\r\n",
Target_Object_Instance,BACNET_MAX_INSTANCE+1);
return 1;
}
if (Target_Object_Property > MAX_BACNET_PROPERTY_ID)
{
fprintf(stderr,"object-type=%u - it must be less than %u\r\n",
Target_Object_Property,MAX_BACNET_PROPERTY_ID+1);
return 1;
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
/* configure standard BACnet/IP port */
bip_set_interface("eth0"); /* for linux */
bip_set_port(0xBAC0);
if (!bip_init())
return 1;
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* no need to spam the world */
I_Am_Request = false;
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,Target_Device_Object_Instance);
/* loop forever */
for (;;)
{
/* increment timer - exit if timed out */
current_seconds = time(NULL);
/* returns 0 bytes on timeout */
pdu_len = bip_receive(
&src,
&Rx_Buf[0],
MAX_MPDU,
timeout);
/* process */
if (pdu_len)
{
npdu_handler(
&src,
&Rx_Buf[0],
pdu_len);
if (argc < 5) {
printf
("%s device-instance object-type object-instance property [index]\r\n",
filename_remove_path(argv[0]));
return 0;
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
if (Error_Detected)
break;
if (I_Am_Request)
{
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
Target_Object_Type = strtol(argv[2], NULL, 0);
Target_Object_Instance = strtol(argv[3], NULL, 0);
Target_Object_Property = strtol(argv[4], NULL, 0);
if (argc > 5)
Target_Object_Index = strtol(argv[5], NULL, 0);
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
else
{
/* wait until the device is bound, or timeout and quit */
found = address_bind_request(
Target_Device_Object_Instance,
&max_apdu,
&Target_Address);
if (found)
{
if (invoke_id == 0)
{
invoke_id = Send_Read_Property_Request(
Target_Device_Object_Instance,
Target_Object_Type,
Target_Object_Instance,
Target_Object_Property,
Target_Object_Index);
}
else if (tsm_invoke_id_free(invoke_id))
break;
}
else
{
if (Target_Object_Type > MAX_BACNET_OBJECT_TYPE) {
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
Target_Object_Type, MAX_BACNET_OBJECT_TYPE + 1);
return 1;
}
if (Target_Object_Instance > BACNET_MAX_INSTANCE) {
fprintf(stderr, "object-instance=%u - it must be less than %u\r\n",
Target_Object_Instance, BACNET_MAX_INSTANCE + 1);
return 1;
}
if (Target_Object_Property > MAX_BACNET_PROPERTY_ID) {
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
Target_Object_Property, MAX_BACNET_PROPERTY_ID + 1);
return 1;
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
/* configure standard BACnet/IP port */
bip_set_interface("eth0"); /* for linux */
bip_set_port(0xBAC0);
if (!bip_init())
return 1;
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* no need to spam the world */
I_Am_Request = false;
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds)
break;
}
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
current_seconds = time(NULL);
return 0;
/* returns 0 bytes on timeout */
pdu_len = bip_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds -
last_seconds) * 1000));
if (Error_Detected)
break;
if (I_Am_Request) {
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
} else {
/* wait until the device is bound, or timeout and quit */
found = address_bind_request(Target_Device_Object_Instance,
&max_apdu, &Target_Address);
if (found) {
if (invoke_id == 0) {
invoke_id =
Send_Read_Property_Request
(Target_Device_Object_Instance, Target_Object_Type,
Target_Object_Instance, Target_Object_Property,
Target_Object_Index);
} else if (tsm_invoke_id_free(invoke_id))
break;
} else {
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds)
break;
}
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
return 0;
}
+175 -212
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -51,253 +51,216 @@
#include "txbuf.h"
// buffer used for receive
static uint8_t Rx_Buf[MAX_MPDU] = {0};
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* global variables used in this file */
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
static BACNET_ADDRESS Target_Address;
static BACNET_REINITIALIZED_STATE Reinitialize_State = BACNET_REINIT_COLDSTART;
static BACNET_REINITIALIZED_STATE Reinitialize_State =
BACNET_REINIT_COLDSTART;
static char *Reinitialize_Password = NULL;
static bool Error_Detected = false;
static void MyErrorHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
static void MyErrorHandler(BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("BACnet Error: %s: %s\r\n",
bactext_error_class_name(error_class),
bactext_error_code_name(error_code));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Error: %s: %s\r\n",
bactext_error_class_name(error_class),
bactext_error_code_name(error_code));
Error_Detected = true;
}
void MyAbortHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
uint8_t abort_reason)
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name(abort_reason));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
uint8_t reject_reason)
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name(reject_reason));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
void MyReinitializeDeviceSimpleAckHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id)
void MyReinitializeDeviceSimpleAckHandler(BACNET_ADDRESS * src,
uint8_t invoke_id)
{
(void)src;
(void)invoke_id;
printf("ReinitializeDevice Acknowledged!\r\n");
(void) src;
(void) invoke_id;
printf("ReinitializeDevice Acknowledged!\r\n");
}
static void Init_Service_Handlers(void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_I_AM,
handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler(
handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the ack coming back */
apdu_set_confirmed_simple_ack_handler(
SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
MyReinitializeDeviceSimpleAckHandler);
/* handle any errors coming back */
apdu_set_error_handler(
SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
MyErrorHandler);
apdu_set_abort_handler(
MyAbortHandler);
apdu_set_reject_handler(
MyRejectHandler);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the ack coming back */
apdu_set_confirmed_simple_ack_handler
(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
MyReinitializeDeviceSimpleAckHandler);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
MyErrorHandler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
#ifdef BIP_DEBUG
static void print_address(
char *name,
BACNET_ADDRESS *dest) // destination address
static void print_address(char *name, BACNET_ADDRESS * dest) // destination address
{
int i = 0; // counter
int i = 0; // counter
if (dest)
{
printf("%s: ",name);
for (i = 0; i < dest->mac_len; i++)
{
printf("%02X",dest->mac[i]);
if (dest) {
printf("%s: ", name);
for (i = 0; i < dest->mac_len; i++) {
printf("%02X", dest->mac[i]);
}
printf("\n");
}
printf("\n");
}
}
#endif
int main(int argc, char *argv[])
{
BACNET_ADDRESS src = {0}; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
uint8_t invoke_id = 0;
bool found = false;
#ifdef BIP_DEBUG
BACNET_ADDRESS my_address, broadcast_address;
#endif
if (argc < 3)
{
/* note: priority 16 and 0 should produce the same end results... */
printf(
"Usage: %s device-instance state [password]\r\n"
"Send BACnet ReinitializeDevice service to device.\r\n"
"\r\n"
"The device-instance can be 0 to %d.\r\n"
"Possible state values:\r\n"
" 0=coldstart\r\n"
" 1=warmstart\r\n"
" 2=startbackup\r\n"
" 3=endbackup\r\n"
" 4=startrestore\r\n"
" 5=endrestore\r\n"
" 6=abortrestore\r\n"
"The optional password is a character string of 1 to 20 characters.\r\n",
filename_remove_path(argv[0]),
BACNET_MAX_INSTANCE-1);
return 0;
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1],NULL,0);
Reinitialize_State = strtol(argv[2],NULL,0);
/* optional password */
if (argc > 3)
Reinitialize_Password = argv[3];
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE)
{
fprintf(stderr,"device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance,BACNET_MAX_INSTANCE);
return 1;
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
/* configure standard BACnet/IP port */
bip_set_interface("eth0"); /* for linux */
bip_set_port(0xBAC0);
if (!bip_init())
return 1;
#ifdef BIP_DEBUG
datalink_get_broadcast_address(&broadcast_address);
print_address("Broadcast",&broadcast_address);
datalink_get_my_address(&my_address);
print_address("Address",&my_address);
#endif
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* don't send an I-Am unless asked */
I_Am_Request = false;
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,Target_Device_Object_Instance);
/* loop forever */
for (;;)
{
/* increment timer - exit if timed out */
current_seconds = time(NULL);
BACNET_ADDRESS src = { 0 }; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
uint8_t invoke_id = 0;
bool found = false;
#ifdef BIP_DEBUG
BACNET_ADDRESS my_address, broadcast_address;
#endif
/* returns 0 bytes on timeout */
pdu_len = bip_receive(
&src,
&Rx_Buf[0],
MAX_MPDU,
timeout);
if (argc < 3) {
/* note: priority 16 and 0 should produce the same end results... */
printf("Usage: %s device-instance state [password]\r\n"
"Send BACnet ReinitializeDevice service to device.\r\n"
"\r\n"
"The device-instance can be 0 to %d.\r\n"
"Possible state values:\r\n"
" 0=coldstart\r\n"
" 1=warmstart\r\n"
" 2=startbackup\r\n"
" 3=endbackup\r\n"
" 4=startrestore\r\n"
" 5=endrestore\r\n"
" 6=abortrestore\r\n"
"The optional password is a character string of 1 to 20 characters.\r\n",
filename_remove_path(argv[0]), BACNET_MAX_INSTANCE - 1);
return 0;
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
Reinitialize_State = strtol(argv[2], NULL, 0);
/* optional password */
if (argc > 3)
Reinitialize_Password = argv[3];
/* process */
if (pdu_len)
{
npdu_handler(
&src,
&Rx_Buf[0],
pdu_len);
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
if (Error_Detected)
break;
if (I_Am_Request)
{
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
}
else
{
/* wait until the device is bound, or timeout and quit */
found = address_bind_request(
Target_Device_Object_Instance,
&max_apdu,
&Target_Address);
if (found)
{
if (invoke_id == 0)
{
invoke_id = Send_Reinitialize_Device_Request(
Target_Device_Object_Instance,
Reinitialize_State,
Reinitialize_Password);
}
else if (tsm_invoke_id_free(invoke_id))
break;
}
else
{
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
/* configure standard BACnet/IP port */
bip_set_interface("eth0"); /* for linux */
bip_set_port(0xBAC0);
if (!bip_init())
return 1;
#ifdef BIP_DEBUG
datalink_get_broadcast_address(&broadcast_address);
print_address("Broadcast", &broadcast_address);
datalink_get_my_address(&my_address);
print_address("Address", &my_address);
#endif
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* don't send an I-Am unless asked */
I_Am_Request = false;
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds)
break;
}
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
current_seconds = time(NULL);
return 0;
/* returns 0 bytes on timeout */
pdu_len = bip_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds -
last_seconds) * 1000));
if (Error_Detected)
break;
if (I_Am_Request) {
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
} else {
/* wait until the device is bound, or timeout and quit */
found = address_bind_request(Target_Device_Object_Instance,
&max_apdu, &Target_Address);
if (found) {
if (invoke_id == 0) {
invoke_id =
Send_Reinitialize_Device_Request
(Target_Device_Object_Instance, Reinitialize_State,
Reinitialize_Password);
} else if (tsm_invoke_id_free(invoke_id))
break;
} else {
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds)
break;
}
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
return 0;
}
+93 -113
View File
@@ -48,136 +48,116 @@
/* This is an example application using the BACnet Stack */
/* 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)
{
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_WHO_HAS,
handler_who_has);
/* set the handler for all the services we don't implement */
/* It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler(
handler_unrecognized_service);
/* Set the handlers for any confirmed services that we support. */
/* We must implement read property - it's required! */
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_WRITE_PROPERTY,
handler_write_property);
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_ATOMIC_READ_FILE,
handler_atomic_read_file);
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
handler_reinitialize_device);
/* handle communication so we can shutup when asked */
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
handler_device_communication_control);
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS,
handler_who_has);
/* set the handler for all the services we don't implement */
/* It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* Set the handlers for any confirmed services that we support. */
/* We must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
handler_write_property);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_ATOMIC_READ_FILE,
handler_atomic_read_file);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_REINITIALIZE_DEVICE,
handler_reinitialize_device);
/* handle communication so we can shutup when asked */
apdu_set_confirmed_handler
(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
handler_device_communication_control);
}
static void cleanup(void)
{
datalink_cleanup();
datalink_cleanup();
}
static void print_address(
char *name,
BACNET_ADDRESS *dest) // destination address
static void print_address(char *name, BACNET_ADDRESS * dest) // destination address
{
int i = 0; // counter
int i = 0; // counter
if (dest)
{
printf("%s: ",name);
for (i = 0; i < dest->mac_len; i++)
{
printf("%02X",dest->mac[i]);
if (dest) {
printf("%s: ", name);
for (i = 0; i < dest->mac_len; i++) {
printf("%02X", dest->mac[i]);
}
printf("\n");
}
printf("\n");
}
}
int main(int argc, char *argv[])
{
BACNET_ADDRESS src = {0}; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
BACNET_ADDRESS my_address, broadcast_address;
time_t last_seconds = 0;
time_t current_seconds = 0;
BACNET_ADDRESS src = { 0 }; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
BACNET_ADDRESS my_address, broadcast_address;
time_t last_seconds = 0;
time_t current_seconds = 0;
/* allow the device ID to be set */
if (argc > 1)
Device_Set_Object_Instance_Number(strtol(argv[1],NULL,0));
if (argc > 2)
bip_set_port(strtol(argv[2],NULL,0));
printf("BACnet Server Demo - Device #%u\r\n",
Device_Object_Instance_Number());
Init_Service_Handlers();
#ifdef BACDL_ETHERNET
// init the physical layer
if (!ethernet_init("eth0"))
return 1;
#endif
#ifdef BACDL_BIP
bip_set_interface("eth0");
if (!bip_init())
return 1;
printf("bip: using port %hu\r\n",bip_get_port());
#endif
#ifdef BACDL_ARCNET
if (!arcnet_init("arc0"))
return 1;
#endif
datalink_get_broadcast_address(&broadcast_address);
print_address("Broadcast",&broadcast_address);
datalink_get_my_address(&my_address);
print_address("Address",&my_address);
atexit(cleanup);
/* configure the timeout values */
last_seconds = time(NULL);
/* broadcast an I-Am on startup */
I_Am_Request = true;
// loop forever
for (;;)
{
// input
current_seconds = time(NULL);
/* allow the device ID to be set */
if (argc > 1)
Device_Set_Object_Instance_Number(strtol(argv[1], NULL, 0));
if (argc > 2)
bip_set_port(strtol(argv[2], NULL, 0));
printf("BACnet Server Demo - Device #%u\r\n",
Device_Object_Instance_Number());
Init_Service_Handlers();
#ifdef BACDL_ETHERNET
// init the physical layer
if (!ethernet_init("eth0"))
return 1;
#endif
#ifdef BACDL_BIP
bip_set_interface("eth0");
if (!bip_init())
return 1;
printf("bip: using port %hu\r\n", bip_get_port());
#endif
#ifdef BACDL_ARCNET
if (!arcnet_init("arc0"))
return 1;
#endif
datalink_get_broadcast_address(&broadcast_address);
print_address("Broadcast", &broadcast_address);
datalink_get_my_address(&my_address);
print_address("Address", &my_address);
atexit(cleanup);
/* configure the timeout values */
last_seconds = time(NULL);
/* broadcast an I-Am on startup */
I_Am_Request = true;
// loop forever
for (;;) {
// input
current_seconds = time(NULL);
// returns 0 bytes on timeout
pdu_len = datalink_receive(
&src,
&Rx_Buf[0],
MAX_MPDU,
timeout);
// returns 0 bytes on timeout
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
// process
if (pdu_len)
{
npdu_handler(
&src,
&Rx_Buf[0],
pdu_len);
// process
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
/* at least one second has passed */
if (current_seconds != last_seconds)
dcc_timer_seconds(current_seconds - last_seconds);
/* send out the I-Am if requested */
if (I_Am_Request) {
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
}
// output
// blink LEDs, Turn on or off outputs, etc
}
/* at least one second has passed */
if (current_seconds != last_seconds)
dcc_timer_seconds(current_seconds - last_seconds);
/* send out the I-Am if requested */
if (I_Am_Request)
{
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
}
// output
// blink LEDs, Turn on or off outputs, etc
}
}
+136 -169
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -50,7 +50,7 @@
#include "txbuf.h"
// buffer used for receive
static uint8_t Rx_Buf[MAX_MPDU] = {0};
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* global variables used in this file */
static BACNET_OBJECT_TYPE Target_Object_Type = MAX_BACNET_OBJECT_TYPE;
@@ -59,191 +59,158 @@ static char *Target_Object_Name = NULL;
static bool Error_Detected = false;
void MyAbortHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
uint8_t abort_reason)
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name(abort_reason));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
uint8_t reject_reason)
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name(reject_reason));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
static void Init_Service_Handlers(void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler(
handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the reply (request) coming back */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_I_HAVE,
handler_i_have);
/* handle any errors coming back */
apdu_set_abort_handler(
MyAbortHandler);
apdu_set_reject_handler(
MyRejectHandler);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the reply (request) coming back */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_HAVE,
handler_i_have);
/* handle any errors coming back */
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
#ifdef BIP_DEBUG
static void print_address(
char *name,
BACNET_ADDRESS *dest) // destination address
static void print_address(char *name, BACNET_ADDRESS * dest) // destination address
{
int i = 0; // counter
int i = 0; // counter
if (dest)
{
printf("%s: ",name);
for (i = 0; i < dest->mac_len; i++)
{
printf("%02X",dest->mac[i]);
if (dest) {
printf("%s: ", name);
for (i = 0; i < dest->mac_len; i++) {
printf("%02X", dest->mac[i]);
}
printf("\n");
}
printf("\n");
}
}
#endif
int main(int argc, char *argv[])
{
BACNET_ADDRESS src = {0}; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
#ifdef BIP_DEBUG
BACNET_ADDRESS my_address, broadcast_address;
#endif
if (argc < 2)
{
/* note: priority 16 and 0 should produce the same end results... */
printf(
"Usage: %s <object-type object-instance | object-name>\r\n"
"Send BACnet WhoHas request to devices, and wait for responses.\r\n"
"\r\n"
"Use either:\r\n"
"The object-type can be 0 to %d.\r\n"
"The object-instance can be 0 to %d.\r\n"
"or:\r\n"
"The object-name can be any string of characters.\r\n",
filename_remove_path(argv[0]),
MAX_BACNET_OBJECT_TYPE-1,
BACNET_MAX_INSTANCE);
return 0;
}
/* decode the command line parameters */
if (argc < 3)
{
Target_Object_Name = argv[1];
}
else
{
Target_Object_Type = strtol(argv[1],NULL,0);
Target_Object_Instance = strtol(argv[2],NULL,0);
if (Target_Object_Instance > BACNET_MAX_INSTANCE)
{
fprintf(stderr,"object-instance=%u - it must be less than %u\r\n",
Target_Object_Instance,BACNET_MAX_INSTANCE+1);
return 1;
}
if (Target_Object_Type > MAX_BACNET_OBJECT_TYPE)
{
fprintf(stderr,"object-type=%u - it must be less than %u\r\n",
Target_Object_Type,MAX_BACNET_OBJECT_TYPE+1);
return 1;
}
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
Init_Service_Handlers();
/* configure standard BACnet/IP port */
bip_set_interface("eth0"); /* for linux */
bip_set_port(0xBAC0);
if (!bip_init())
return 1;
#ifdef BIP_DEBUG
datalink_get_broadcast_address(&broadcast_address);
print_address("Broadcast",&broadcast_address);
datalink_get_my_address(&my_address);
print_address("Address",&my_address);
#endif
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = Device_APDU_Timeout() / 1000;
/* don't send an I-Am unless asked */
I_Am_Request = false;
/* send the request */
if (argc < 3)
Send_WhoHas_Name(-1, -1, Target_Object_Name);
else
Send_WhoHas_Object(-1, -1,
Target_Object_Type,
Target_Object_Instance);
/* loop forever */
for (;;)
{
/* increment timer - exit if timed out */
current_seconds = time(NULL);
/* returns 0 bytes on timeout */
pdu_len = bip_receive(
&src,
&Rx_Buf[0],
MAX_MPDU,
timeout);
/* process */
if (pdu_len)
{
npdu_handler(
&src,
&Rx_Buf[0],
pdu_len);
}
if (Error_Detected)
break;
if (I_Am_Request)
{
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
}
else
{
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds)
break;
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
BACNET_ADDRESS src = { 0 }; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
#ifdef BIP_DEBUG
BACNET_ADDRESS my_address, broadcast_address;
#endif
return 0;
if (argc < 2) {
/* note: priority 16 and 0 should produce the same end results... */
printf("Usage: %s <object-type object-instance | object-name>\r\n"
"Send BACnet WhoHas request to devices, and wait for responses.\r\n"
"\r\n"
"Use either:\r\n"
"The object-type can be 0 to %d.\r\n"
"The object-instance can be 0 to %d.\r\n"
"or:\r\n"
"The object-name can be any string of characters.\r\n",
filename_remove_path(argv[0]),
MAX_BACNET_OBJECT_TYPE - 1, BACNET_MAX_INSTANCE);
return 0;
}
/* decode the command line parameters */
if (argc < 3) {
Target_Object_Name = argv[1];
} else {
Target_Object_Type = strtol(argv[1], NULL, 0);
Target_Object_Instance = strtol(argv[2], NULL, 0);
if (Target_Object_Instance > BACNET_MAX_INSTANCE) {
fprintf(stderr,
"object-instance=%u - it must be less than %u\r\n",
Target_Object_Instance, BACNET_MAX_INSTANCE + 1);
return 1;
}
if (Target_Object_Type > MAX_BACNET_OBJECT_TYPE) {
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
Target_Object_Type, MAX_BACNET_OBJECT_TYPE + 1);
return 1;
}
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
Init_Service_Handlers();
/* configure standard BACnet/IP port */
bip_set_interface("eth0"); /* for linux */
bip_set_port(0xBAC0);
if (!bip_init())
return 1;
#ifdef BIP_DEBUG
datalink_get_broadcast_address(&broadcast_address);
print_address("Broadcast", &broadcast_address);
datalink_get_my_address(&my_address);
print_address("Address", &my_address);
#endif
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = Device_APDU_Timeout() / 1000;
/* don't send an I-Am unless asked */
I_Am_Request = false;
/* send the request */
if (argc < 3)
Send_WhoHas_Name(-1, -1, Target_Object_Name);
else
Send_WhoHas_Object(-1, -1,
Target_Object_Type, Target_Object_Instance);
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
current_seconds = time(NULL);
/* returns 0 bytes on timeout */
pdu_len = bip_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
if (Error_Detected)
break;
if (I_Am_Request) {
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
} else {
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds)
break;
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
return 0;
}
+265 -336
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -49,7 +49,7 @@
#include "txbuf.h"
// buffer used for receive
static uint8_t Rx_Buf[MAX_MPDU] = {0};
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* global variables used in this file */
static uint32_t Target_File_Object_Instance = 4194303;
@@ -60,378 +60,307 @@ static bool End_Of_File_Detected = false;
static bool Error_Detected = false;
static uint8_t Current_Invoke_ID = 0;
static void Atomic_Read_File_Error_Handler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
static void Atomic_Read_File_Error_Handler(BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("\r\nBACnet Error!\r\n");
printf("Error Class: %s\r\n",
bactext_error_class_name(error_class));
printf("Error Code: %s\r\n",
bactext_error_code_name(error_code));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("\r\nBACnet Error!\r\n");
printf("Error Class: %s\r\n", bactext_error_class_name(error_class));
printf("Error Code: %s\r\n", bactext_error_code_name(error_code));
Error_Detected = true;
}
void MyAbortHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
uint8_t abort_reason)
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("\r\nBACnet Abort!\r\n");
printf("Abort Reason: %s\r\n",
bactext_abort_reason_name(abort_reason));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("\r\nBACnet Abort!\r\n");
printf("Abort Reason: %s\r\n",
bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
uint8_t reject_reason)
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("\r\nBACnet Reject!\r\n");
printf("Reject Reason: %s\r\n",
bactext_reject_reason_name(reject_reason));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("\r\nBACnet Reject!\r\n");
printf("Reject Reason: %s\r\n",
bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
static uint8_t Send_Atomic_Write_File_Stream(
uint32_t device_id,
uint32_t file_instance,
int fileStartPosition,
BACNET_OCTET_STRING *fileData)
static uint8_t Send_Atomic_Write_File_Stream(uint32_t device_id,
uint32_t file_instance,
int fileStartPosition, BACNET_OCTET_STRING * fileData)
{
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_ATOMIC_WRITE_FILE_DATA data;
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_ATOMIC_WRITE_FILE_DATA data;
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
status = tsm_transaction_available();
if (status)
{
datalink_get_my_address(&my_address);
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
&dest,
&my_address,
true, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
invoke_id = tsm_next_free_invokeID();
// load the data for the encoding
data.object_type = OBJECT_FILE;
data.object_instance = file_instance;
data.access = FILE_STREAM_ACCESS;
data.type.stream.fileStartPosition = fileStartPosition;
status = octetstring_copy(&data.fileData, fileData);
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
{
pdu_len += awf_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
invoke_id,
&data);
/* will the APDU fit the target device?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned)pdu_len <= max_apdu)
{
tsm_set_confirmed_unsegmented_transaction(
invoke_id,
&dest,
&Handler_Transmit_Buffer[0],
pdu_len);
bytes_sent = datalink_send_pdu(
&dest, // destination address
&Handler_Transmit_Buffer[0],
pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,"Failed to Send AtomicWriteFile Request (%s)!\n",
strerror(errno));
}
else
fprintf(stderr,"Failed to Send AtomicWriteFile Request "
"(payload [%d] exceeds destination maximum APDU [%u])!\n",
pdu_len,max_apdu);
}
else
fprintf(stderr,"Failed to Send AtomicWriteFile Request "
"(payload [%d] exceeds octet string capacity)!\n",pdu_len);
}
status = tsm_transaction_available();
if (status) {
datalink_get_my_address(&my_address);
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, &my_address, true, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
return invoke_id;
invoke_id = tsm_next_free_invokeID();
// load the data for the encoding
data.object_type = OBJECT_FILE;
data.object_instance = file_instance;
data.access = FILE_STREAM_ACCESS;
data.type.stream.fileStartPosition = fileStartPosition;
status = octetstring_copy(&data.fileData, fileData);
if (status) {
pdu_len += awf_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
invoke_id, &data);
/* will the APDU fit the target device?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned) pdu_len <= max_apdu) {
tsm_set_confirmed_unsegmented_transaction(invoke_id,
&dest, &Handler_Transmit_Buffer[0], pdu_len);
bytes_sent = datalink_send_pdu(&dest, // destination address
&Handler_Transmit_Buffer[0], pdu_len); // number of bytes of data
if (bytes_sent <= 0)
fprintf(stderr,
"Failed to Send AtomicWriteFile Request (%s)!\n",
strerror(errno));
} else
fprintf(stderr, "Failed to Send AtomicWriteFile Request "
"(payload [%d] exceeds destination maximum APDU [%u])!\n",
pdu_len, max_apdu);
} else
fprintf(stderr, "Failed to Send AtomicWriteFile Request "
"(payload [%d] exceeds octet string capacity)!\n",
pdu_len);
}
return invoke_id;
}
static void Send_WhoIs(uint32_t device_id)
{
int pdu_len = 0;
BACNET_ADDRESS dest;
int bytes_sent = 0;
int pdu_len = 0;
BACNET_ADDRESS dest;
int bytes_sent = 0;
/* Who-Is is a global broadcast */
datalink_get_broadcast_address(&dest);
/* Who-Is is a global broadcast */
datalink_get_broadcast_address(&dest);
/* encode the NPDU portion of the packet */
pdu_len = npdu_encode_apdu(
&Handler_Transmit_Buffer[0],
&dest,
NULL,
false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
/* encode the NPDU portion of the packet */
pdu_len = npdu_encode_apdu(&Handler_Transmit_Buffer[0], &dest, NULL, false, // true for confirmed messages
MESSAGE_PRIORITY_NORMAL);
/* encode the APDU portion of the packet */
pdu_len += whois_encode_apdu(
&Handler_Transmit_Buffer[pdu_len],
device_id,
device_id);
/* encode the APDU portion of the packet */
pdu_len += whois_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
device_id, device_id);
bytes_sent = datalink_send_pdu(
&dest, /* destination address */
&Handler_Transmit_Buffer[0],
pdu_len); /* number of bytes of data */
if (bytes_sent <= 0)
fprintf(stderr,"Failed to Send Who-Is Request (%s)!\n", strerror(errno));
bytes_sent = datalink_send_pdu(&dest, /* destination address */
&Handler_Transmit_Buffer[0], pdu_len); /* number of bytes of data */
if (bytes_sent <= 0)
fprintf(stderr, "Failed to Send Who-Is Request (%s)!\n",
strerror(errno));
}
static void LocalIAmHandler(
uint8_t *service_request,
uint16_t service_len,
BACNET_ADDRESS *src)
static void LocalIAmHandler(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src)
{
int len = 0;
uint32_t device_id = 0;
unsigned max_apdu = 0;
int segmentation = 0;
uint16_t vendor_id = 0;
int len = 0;
uint32_t device_id = 0;
unsigned max_apdu = 0;
int segmentation = 0;
uint16_t vendor_id = 0;
(void)src;
(void)service_len;
len = iam_decode_service_request(
service_request,
&device_id,
&max_apdu,
&segmentation,
&vendor_id);
if (len != -1)
{
address_add(device_id,
max_apdu,
src);
}
else
fprintf(stderr,"!\n");
(void) src;
(void) service_len;
len = iam_decode_service_request(service_request,
&device_id, &max_apdu, &segmentation, &vendor_id);
if (len != -1) {
address_add(device_id, max_apdu, src);
} else
fprintf(stderr, "!\n");
return;
return;
}
static void Init_Service_Handlers(void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_I_AM,
LocalIAmHandler);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler(
handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle any errors coming back */
apdu_set_error_handler(
SERVICE_CONFIRMED_ATOMIC_READ_FILE,
Atomic_Read_File_Error_Handler);
apdu_set_abort_handler(
MyAbortHandler);
apdu_set_reject_handler(
MyRejectHandler);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
LocalIAmHandler);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_ATOMIC_READ_FILE,
Atomic_Read_File_Error_Handler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
int main(int argc, char *argv[])
{
BACNET_ADDRESS src = {0}; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
int fileStartPosition = 0;
unsigned requestedOctetCount = 0;
uint8_t invoke_id = 0;
bool found = false;
uint16_t my_max_apdu = 0;
FILE *pFile = NULL;
static BACNET_OCTET_STRING fileData;
size_t len = 0;
if (argc < 4)
{
/* FIXME: what about access method - record or stream? */
printf("%s device-instance file-instance local-name\r\n",
filename_remove_path(argv[0]));
return 0;
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1],NULL,0);
Target_File_Object_Instance = strtol(argv[2],NULL,0);
Local_File_Name = argv[3];
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE)
{
fprintf(stderr,"device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance,BACNET_MAX_INSTANCE);
return 1;
}
if (Target_File_Object_Instance >= BACNET_MAX_INSTANCE)
{
fprintf(stderr,"file-instance=%u - it must be less than %u\r\n",
Target_File_Object_Instance,BACNET_MAX_INSTANCE+1);
return 1;
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
/* configure standard BACnet/IP port */
bip_set_interface("eth0"); /* for linux */
bip_set_port(0xBAC0);
if (!bip_init())
return 1;
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance);
/* loop forever */
for (;;)
{
/* increment timer - exit if timed out */
current_seconds = time(NULL);
BACNET_ADDRESS src = { 0 }; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
int fileStartPosition = 0;
unsigned requestedOctetCount = 0;
uint8_t invoke_id = 0;
bool found = false;
uint16_t my_max_apdu = 0;
FILE *pFile = NULL;
static BACNET_OCTET_STRING fileData;
size_t len = 0;
/* returns 0 bytes on timeout */
pdu_len = bip_receive(
&src,
&Rx_Buf[0],
MAX_MPDU,
timeout);
/* process */
if (pdu_len)
{
npdu_handler(
&src,
&Rx_Buf[0],
pdu_len);
if (argc < 4) {
/* FIXME: what about access method - record or stream? */
printf("%s device-instance file-instance local-name\r\n",
filename_remove_path(argv[0]));
return 0;
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
if (End_Of_File_Detected || Error_Detected)
{
printf("\r\n");
break;
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
Target_File_Object_Instance = strtol(argv[2], NULL, 0);
Local_File_Name = argv[3];
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
if (I_Am_Request)
{
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
if (Target_File_Object_Instance >= BACNET_MAX_INSTANCE) {
fprintf(stderr, "file-instance=%u - it must be less than %u\r\n",
Target_File_Object_Instance, BACNET_MAX_INSTANCE + 1);
return 1;
}
else
{
/* wait until the device is bound, or timeout and quit */
found = address_bind_request(
Target_Device_Object_Instance,
&max_apdu,
&Target_Address);
if (found)
{
/* calculate the smaller of our APDU size or theirs
and remove the overhead of the APDU (varies depending on size).
note: we could fail if there is a bottle neck (router)
and smaller MPDU in betweeen. */
if (max_apdu < MAX_APDU)
my_max_apdu = max_apdu;
else
my_max_apdu = MAX_APDU;
/* Typical sizes are 50, 128, 206, 480, 1024, and 1476 octets */
if (my_max_apdu <= 50)
requestedOctetCount = my_max_apdu - 16;
else if (my_max_apdu <= 480)
requestedOctetCount = my_max_apdu - 32;
else if (my_max_apdu <= 1476)
requestedOctetCount = my_max_apdu - 64;
else
requestedOctetCount = my_max_apdu / 2;
/* has the previous invoke id expired or returned?
note: invoke ID = 0 is invalid, so it will be idle */
if ((invoke_id == 0) || tsm_invoke_id_free(invoke_id))
{
if (invoke_id != 0)
fileStartPosition += requestedOctetCount;
/* we'll read the file in chunks
less than max_apdu to keep unsegmented */
pFile = fopen(Local_File_Name,"rb");
if (pFile)
{
(void)fseek(pFile,
fileStartPosition,
SEEK_SET);
len = fread(octetstring_value(&fileData), 1,
requestedOctetCount, pFile);
if (len < requestedOctetCount)
End_Of_File_Detected = true;
octetstring_truncate(&fileData,len);
fclose(pFile);
}
else
End_Of_File_Detected = true;
printf("\rSending %d bytes",(fileStartPosition+len));
invoke_id = Send_Atomic_Write_File_Stream(
Target_Device_Object_Instance,
Target_File_Object_Instance,
fileStartPosition,
&fileData);
Current_Invoke_ID = invoke_id;
}
}
else
{
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
/* configure standard BACnet/IP port */
bip_set_interface("eth0"); /* for linux */
bip_set_port(0xBAC0);
if (!bip_init())
return 1;
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance);
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds)
break;
}
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
current_seconds = time(NULL);
return 0;
/* returns 0 bytes on timeout */
pdu_len = bip_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds -
last_seconds) * 1000));
if (End_Of_File_Detected || Error_Detected) {
printf("\r\n");
break;
}
if (I_Am_Request) {
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
} else {
/* wait until the device is bound, or timeout and quit */
found = address_bind_request(Target_Device_Object_Instance,
&max_apdu, &Target_Address);
if (found) {
/* calculate the smaller of our APDU size or theirs
and remove the overhead of the APDU (varies depending on size).
note: we could fail if there is a bottle neck (router)
and smaller MPDU in betweeen. */
if (max_apdu < MAX_APDU)
my_max_apdu = max_apdu;
else
my_max_apdu = MAX_APDU;
/* Typical sizes are 50, 128, 206, 480, 1024, and 1476 octets */
if (my_max_apdu <= 50)
requestedOctetCount = my_max_apdu - 16;
else if (my_max_apdu <= 480)
requestedOctetCount = my_max_apdu - 32;
else if (my_max_apdu <= 1476)
requestedOctetCount = my_max_apdu - 64;
else
requestedOctetCount = my_max_apdu / 2;
/* has the previous invoke id expired or returned?
note: invoke ID = 0 is invalid, so it will be idle */
if ((invoke_id == 0) || tsm_invoke_id_free(invoke_id)) {
if (invoke_id != 0)
fileStartPosition += requestedOctetCount;
/* we'll read the file in chunks
less than max_apdu to keep unsegmented */
pFile = fopen(Local_File_Name, "rb");
if (pFile) {
(void) fseek(pFile, fileStartPosition, SEEK_SET);
len = fread(octetstring_value(&fileData), 1,
requestedOctetCount, pFile);
if (len < requestedOctetCount)
End_Of_File_Detected = true;
octetstring_truncate(&fileData, len);
fclose(pFile);
} else
End_Of_File_Detected = true;
printf("\rSending %d bytes",
(fileStartPosition + len));
invoke_id =
Send_Atomic_Write_File_Stream
(Target_Device_Object_Instance,
Target_File_Object_Instance, fileStartPosition,
&fileData);
Current_Invoke_ID = invoke_id;
}
} else {
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds)
break;
}
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
return 0;
}
+252 -294
View File
@@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h> /* for time */
#include <time.h> /* for time */
#include <errno.h>
#include "bactext.h"
#include "iam.h"
@@ -50,7 +50,7 @@
#include "txbuf.h"
// buffer used for receive
static uint8_t Rx_Buf[MAX_MPDU] = {0};
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* global variables used in this file */
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
@@ -59,326 +59,284 @@ static BACNET_OBJECT_TYPE Target_Object_Type = OBJECT_ANALOG_INPUT;
static BACNET_PROPERTY_ID Target_Object_Property = PROP_ACKED_TRANSITIONS;
/* array index value or BACNET_ARRAY_ALL */
static int32_t Target_Object_Property_Index = BACNET_ARRAY_ALL;
static BACNET_APPLICATION_TAG Target_Object_Property_Tag = BACNET_APPLICATION_TAG_NULL;
static BACNET_APPLICATION_DATA_VALUE Target_Object_Property_Value = {0};
static BACNET_APPLICATION_TAG Target_Object_Property_Tag =
BACNET_APPLICATION_TAG_NULL;
static BACNET_APPLICATION_DATA_VALUE Target_Object_Property_Value = { 0 };
/* 0 if not set, 1..16 if set */
static uint8_t Target_Object_Property_Priority = 0;
static BACNET_ADDRESS Target_Address;
static bool Error_Detected = false;
static void MyErrorHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
static void MyErrorHandler(BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("\r\nBACnet Error!\r\n");
printf("Error Class: %s\r\n",
bactext_error_class_name(error_class));
printf("Error Code: %s\r\n",
bactext_error_code_name(error_code));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("\r\nBACnet Error!\r\n");
printf("Error Class: %s\r\n", bactext_error_class_name(error_class));
printf("Error Code: %s\r\n", bactext_error_code_name(error_code));
Error_Detected = true;
}
void MyAbortHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
uint8_t abort_reason)
void MyAbortHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t abort_reason)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("\r\nBACnet Abort!\r\n");
printf("Abort Reason: %s\r\n",
bactext_abort_reason_name(abort_reason));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("\r\nBACnet Abort!\r\n");
printf("Abort Reason: %s\r\n",
bactext_abort_reason_name(abort_reason));
Error_Detected = true;
}
void MyRejectHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id,
uint8_t reject_reason)
void MyRejectHandler(BACNET_ADDRESS * src,
uint8_t invoke_id, uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void)src;
(void)invoke_id;
printf("\r\nBACnet Reject!\r\n");
printf("Reject Reason: %s\r\n",
bactext_reject_reason_name(reject_reason));
Error_Detected = true;
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("\r\nBACnet Reject!\r\n");
printf("Reject Reason: %s\r\n",
bactext_reject_reason_name(reject_reason));
Error_Detected = true;
}
void MyWritePropertySimpleAckHandler(
BACNET_ADDRESS *src,
uint8_t invoke_id)
void MyWritePropertySimpleAckHandler(BACNET_ADDRESS * src,
uint8_t invoke_id)
{
(void)src;
(void)invoke_id;
printf("\r\nWriteProperty Acknowledged!\r\n");
(void) src;
(void) invoke_id;
printf("\r\nWriteProperty Acknowledged!\r\n");
}
static void Init_Service_Handlers(void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(
SERVICE_UNCONFIRMED_I_AM,
handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler(
handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(
SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the ack coming back */
apdu_set_confirmed_simple_ack_handler(
SERVICE_CONFIRMED_WRITE_PROPERTY,
MyWritePropertySimpleAckHandler);
/* handle any errors coming back */
apdu_set_error_handler(
SERVICE_CONFIRMED_WRITE_PROPERTY,
MyErrorHandler);
apdu_set_abort_handler(
MyAbortHandler);
apdu_set_reject_handler(
MyRejectHandler);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
/* handle the ack coming back */
apdu_set_confirmed_simple_ack_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
MyWritePropertySimpleAckHandler);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
MyErrorHandler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
int main(int argc, char *argv[])
{
BACNET_ADDRESS src = {0}; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
uint8_t invoke_id = 0;
bool found = false;
char *value_string = NULL;
bool status = false;
if (argc < 7)
{
/* note: priority 16 and 0 should produce the same end results... */
printf("Usage: %s device-instance object-type object-instance "
"property tag value [priority] [index]\r\n"
"\r\n"
"device-instance:\r\n"
"BACnet Device Object Instance number that you are trying to\r\n"
"communicate to. This number will be used to try and bind with\r\n"
"the device using Who-Is and I-Am services. For example, if you were\r\n"
"writing to Device Object 123, the device-instance would be 123.\r\n"
"\r\n"
"object-type:\r\n"
"The object type is the integer value of the enumeration\r\n"
"BACNET_OBJECT_TYPE in bacenum.h. It is the object that you are\r\n"
"writing to. For example if you were writing to Analog Output 2, \r\n"
"the object-type would be 1.\r\n"
"\r\n"
"object-instance:\r\n"
"This is the object instance number of the object that you are \r\n"
"writing to. For example, if you were writing to Analog Output 2, \r\n"
"the object-instance would be 2.\r\n"
"\r\n"
"property:\r\n"
"The property is an integer value of the enumeration \r\n"
"BACNET_PROPERTY_ID in bacenum.h. It is the property you are \r\n"
"writing to. For example, if you were writing to the Present Value\r\n"
"property, you would use 85 as the property.\r\n"
"\r\n"
"tag:\r\n"
"Tag is the integer value of the enumeration BACNET_APPLICATION_TAG \r\n"
"in bacenum.h. It is the data type of the value that you are\r\n"
"writing. For example, if you were writing a REAL value, you would \r\n"
"use a tag of 4."
"\r\n"
"value:\r\n"
"The value is an ASCII representation of some type of data that you\r\n"
"are writing. It is encoded using the tag information provided. For\r\n"
"example, if you were writing a REAL value of 100.0, you would use \r\n"
"100.0 as the value.\r\n"
"\r\n"
"[priority]:\r\n"
"This optional parameter is used for setting the priority of the\r\n"
"write. If no priority is given, none is sent, and the BACnet \r\n"
"standard requires that the value is written at the lowest \r\n"
"priority (16) if the object property supports priorities.\r\n"
"\r\n"
"[index]\r\n"
"This optional integer parameter is the index number of an array.\r\n"
"If the property is an array, individual elements can be written\r\n"
"to if supported.\r\n"
"\r\n"
"Here is a brief overview of BACnet property and tags:\r\n"
"Certain properties are expected to be written with certain \r\n"
"application tags, so you probably need to know which ones to use\r\n"
"with each property of each object. It is almost safe to say that\r\n"
"given a property and an object and a table, the tag could be looked\r\n"
"up automatically. There may be a few exceptions to this, such as\r\n"
"the Any property type in the schedule object and the Present Value\r\n"
"accepting REAL, BOOLEAN, NULL, etc. Perhaps it would be simpler for\r\n"
"the demo to use this kind of table - but I also wanted to be able\r\n"
"to do negative testing by passing the wrong tag and have the server\r\n"
"return a reject message.\r\n"
"\r\n"
"Example:\r\n"
"If you want send a 100 to the Present-Value in the Analog Output\r\n"
"at priority 16, you could send the following command:\r\n"
"%s 123 1 0 85 4 100\r\n"
"You could also send a relinquish command:\r\n"
"%s 123 1 0 85 0 0\r\n",
filename_remove_path(argv[0]),
filename_remove_path(argv[0]),
filename_remove_path(argv[0]));
return 0;
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1],NULL,0);
Target_Object_Type = strtol(argv[2],NULL,0);
Target_Object_Instance = strtol(argv[3],NULL,0);
Target_Object_Property = strtol(argv[4],NULL,0);
Target_Object_Property_Tag = strtol(argv[5],NULL,0);
value_string = argv[6];
/* optional priority */
if (argc > 7)
Target_Object_Property_Priority = strtol(argv[7],NULL,0);
/* optional index */
if (argc > 8)
Target_Object_Property_Index = strtol(argv[8],NULL,0);
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE)
{
fprintf(stderr,"device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance,BACNET_MAX_INSTANCE);
return 1;
}
if (Target_Object_Type > MAX_BACNET_OBJECT_TYPE)
{
fprintf(stderr,"object-type=%u - it must be less than %u\r\n",
Target_Object_Type,MAX_BACNET_OBJECT_TYPE+1);
return 1;
}
if (Target_Object_Instance > BACNET_MAX_INSTANCE)
{
fprintf(stderr,"object-instance=%u - it must be less than %u\r\n",
Target_Object_Instance,BACNET_MAX_INSTANCE+1);
return 1;
}
if (Target_Object_Property > MAX_BACNET_PROPERTY_ID)
{
fprintf(stderr,"object-type=%u - it must be less than %u\r\n",
Target_Object_Property,MAX_BACNET_PROPERTY_ID+1);
return 1;
}
if (Target_Object_Property_Tag >= MAX_BACNET_APPLICATION_TAG)
{
fprintf(stderr,"tag=%u - it must be less than %u\r\n",
Target_Object_Property_Tag,MAX_BACNET_APPLICATION_TAG);
return 1;
}
status = bacapp_parse_application_data(
Target_Object_Property_Tag,
value_string,
&Target_Object_Property_Value);
if (!status)
{
/* FIXME: show the expected entry format for the tag */
fprintf(stderr,"unable to parse the tag value\r\n");
return 1;
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
/* configure standard BACnet/IP port */
bip_set_interface("eth0"); /* for linux */
bip_set_port(0xBAC0);
if (!bip_init())
return 1;
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,Target_Device_Object_Instance);
/* loop forever */
for (;;)
{
/* increment timer - exit if timed out */
current_seconds = time(NULL);
BACNET_ADDRESS src = { 0 }; // address where message came from
uint16_t pdu_len = 0;
unsigned timeout = 100; // milliseconds
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
uint8_t invoke_id = 0;
bool found = false;
char *value_string = NULL;
bool status = false;
/* returns 0 bytes on timeout */
pdu_len = bip_receive(
&src,
&Rx_Buf[0],
MAX_MPDU,
timeout);
if (argc < 7) {
/* note: priority 16 and 0 should produce the same end results... */
printf("Usage: %s device-instance object-type object-instance "
"property tag value [priority] [index]\r\n"
"\r\n"
"device-instance:\r\n"
"BACnet Device Object Instance number that you are trying to\r\n"
"communicate to. This number will be used to try and bind with\r\n"
"the device using Who-Is and I-Am services. For example, if you were\r\n"
"writing to Device Object 123, the device-instance would be 123.\r\n"
"\r\n"
"object-type:\r\n"
"The object type is the integer value of the enumeration\r\n"
"BACNET_OBJECT_TYPE in bacenum.h. It is the object that you are\r\n"
"writing to. For example if you were writing to Analog Output 2, \r\n"
"the object-type would be 1.\r\n"
"\r\n"
"object-instance:\r\n"
"This is the object instance number of the object that you are \r\n"
"writing to. For example, if you were writing to Analog Output 2, \r\n"
"the object-instance would be 2.\r\n"
"\r\n"
"property:\r\n"
"The property is an integer value of the enumeration \r\n"
"BACNET_PROPERTY_ID in bacenum.h. It is the property you are \r\n"
"writing to. For example, if you were writing to the Present Value\r\n"
"property, you would use 85 as the property.\r\n"
"\r\n"
"tag:\r\n"
"Tag is the integer value of the enumeration BACNET_APPLICATION_TAG \r\n"
"in bacenum.h. It is the data type of the value that you are\r\n"
"writing. For example, if you were writing a REAL value, you would \r\n"
"use a tag of 4."
"\r\n"
"value:\r\n"
"The value is an ASCII representation of some type of data that you\r\n"
"are writing. It is encoded using the tag information provided. For\r\n"
"example, if you were writing a REAL value of 100.0, you would use \r\n"
"100.0 as the value.\r\n"
"\r\n"
"[priority]:\r\n"
"This optional parameter is used for setting the priority of the\r\n"
"write. If no priority is given, none is sent, and the BACnet \r\n"
"standard requires that the value is written at the lowest \r\n"
"priority (16) if the object property supports priorities.\r\n"
"\r\n"
"[index]\r\n"
"This optional integer parameter is the index number of an array.\r\n"
"If the property is an array, individual elements can be written\r\n"
"to if supported.\r\n"
"\r\n"
"Here is a brief overview of BACnet property and tags:\r\n"
"Certain properties are expected to be written with certain \r\n"
"application tags, so you probably need to know which ones to use\r\n"
"with each property of each object. It is almost safe to say that\r\n"
"given a property and an object and a table, the tag could be looked\r\n"
"up automatically. There may be a few exceptions to this, such as\r\n"
"the Any property type in the schedule object and the Present Value\r\n"
"accepting REAL, BOOLEAN, NULL, etc. Perhaps it would be simpler for\r\n"
"the demo to use this kind of table - but I also wanted to be able\r\n"
"to do negative testing by passing the wrong tag and have the server\r\n"
"return a reject message.\r\n"
"\r\n"
"Example:\r\n"
"If you want send a 100 to the Present-Value in the Analog Output\r\n"
"at priority 16, you could send the following command:\r\n"
"%s 123 1 0 85 4 100\r\n"
"You could also send a relinquish command:\r\n"
"%s 123 1 0 85 0 0\r\n",
filename_remove_path(argv[0]),
filename_remove_path(argv[0]), filename_remove_path(argv[0]));
return 0;
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
Target_Object_Type = strtol(argv[2], NULL, 0);
Target_Object_Instance = strtol(argv[3], NULL, 0);
Target_Object_Property = strtol(argv[4], NULL, 0);
Target_Object_Property_Tag = strtol(argv[5], NULL, 0);
value_string = argv[6];
/* optional priority */
if (argc > 7)
Target_Object_Property_Priority = strtol(argv[7], NULL, 0);
/* optional index */
if (argc > 8)
Target_Object_Property_Index = strtol(argv[8], NULL, 0);
/* process */
if (pdu_len)
{
npdu_handler(
&src,
&Rx_Buf[0],
pdu_len);
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
if (Error_Detected)
break;
if (I_Am_Request)
{
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
if (Target_Object_Type > MAX_BACNET_OBJECT_TYPE) {
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
Target_Object_Type, MAX_BACNET_OBJECT_TYPE + 1);
return 1;
}
else
{
/* wait until the device is bound, or timeout and quit */
found = address_bind_request(
Target_Device_Object_Instance,
&max_apdu,
&Target_Address);
if (found)
{
if (invoke_id == 0)
{
invoke_id = Send_Write_Property_Request(
Target_Device_Object_Instance,
Target_Object_Type,
Target_Object_Instance,
Target_Object_Property,
&Target_Object_Property_Value,
Target_Object_Property_Priority,
Target_Object_Property_Index);
}
else if (tsm_invoke_id_free(invoke_id))
break;
}
else
{
if (Target_Object_Instance > BACNET_MAX_INSTANCE) {
fprintf(stderr, "object-instance=%u - it must be less than %u\r\n",
Target_Object_Instance, BACNET_MAX_INSTANCE + 1);
return 1;
}
if (Target_Object_Property > MAX_BACNET_PROPERTY_ID) {
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
Target_Object_Property, MAX_BACNET_PROPERTY_ID + 1);
return 1;
}
if (Target_Object_Property_Tag >= MAX_BACNET_APPLICATION_TAG) {
fprintf(stderr, "tag=%u - it must be less than %u\r\n",
Target_Object_Property_Tag, MAX_BACNET_APPLICATION_TAG);
return 1;
}
status = bacapp_parse_application_data(Target_Object_Property_Tag,
value_string, &Target_Object_Property_Value);
if (!status) {
/* FIXME: show the expected entry format for the tag */
fprintf(stderr, "unable to parse the tag value\r\n");
return 1;
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
/* configure standard BACnet/IP port */
bip_set_interface("eth0"); /* for linux */
bip_set_port(0xBAC0);
if (!bip_init())
return 1;
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (Device_APDU_Timeout() / 1000) *
Device_Number_Of_APDU_Retries();
/* try to bind with the device */
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds)
break;
}
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
current_seconds = time(NULL);
return 0;
/* returns 0 bytes on timeout */
pdu_len = bip_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds -
last_seconds) * 1000));
if (Error_Detected)
break;
if (I_Am_Request) {
I_Am_Request = false;
iam_send(&Handler_Transmit_Buffer[0]);
} else {
/* wait until the device is bound, or timeout and quit */
found = address_bind_request(Target_Device_Object_Instance,
&max_apdu, &Target_Address);
if (found) {
if (invoke_id == 0) {
invoke_id =
Send_Write_Property_Request
(Target_Device_Object_Instance, Target_Object_Type,
Target_Object_Instance, Target_Object_Property,
&Target_Object_Property_Value,
Target_Object_Property_Priority,
Target_Object_Property_Index);
} else if (tsm_invoke_id_free(invoke_id))
break;
} else {
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds)
break;
}
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
return 0;
}