Indented.
This commit is contained in:
@@ -426,8 +426,8 @@ static bool cov_subscribe(
|
||||
|
||||
switch (cov_data->monitoredObjectIdentifier.type) {
|
||||
case OBJECT_BINARY_INPUT:
|
||||
if (Binary_Input_Valid_Instance(
|
||||
cov_data->monitoredObjectIdentifier.instance)) {
|
||||
if (Binary_Input_Valid_Instance(cov_data->
|
||||
monitoredObjectIdentifier.instance)) {
|
||||
status =
|
||||
cov_list_subscribe(src, cov_data, error_class, error_code);
|
||||
} else {
|
||||
|
||||
@@ -244,8 +244,7 @@ int RPM_Encode_Property(
|
||||
rpm_ack_encode_apdu_object_property_error(&Temp_Buf[0],
|
||||
error_class, error_code);
|
||||
len =
|
||||
memcopy(&apdu[0], &Temp_Buf[0], offset + apdu_len, len,
|
||||
max_apdu);
|
||||
memcopy(&apdu[0], &Temp_Buf[0], offset + apdu_len, len, max_apdu);
|
||||
if (!len) {
|
||||
return 0;
|
||||
}
|
||||
@@ -344,8 +343,8 @@ void handler_read_property_multiple(
|
||||
rpm_ack_encode_apdu_object_begin(&Temp_Buf[0], object_type,
|
||||
object_instance);
|
||||
copy_len =
|
||||
memcopy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
|
||||
apdu_len, len, sizeof(Handler_Transmit_Buffer));
|
||||
memcopy(&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0], apdu_len,
|
||||
len, sizeof(Handler_Transmit_Buffer));
|
||||
if (!copy_len) {
|
||||
apdu_len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
|
||||
|
||||
@@ -45,11 +45,11 @@
|
||||
/* note: initial the linked list of read_access_data */
|
||||
static int rpm_ack_decode_service_request(
|
||||
uint8_t * apdu,
|
||||
int apdu_len, /* total length of the apdu */
|
||||
int apdu_len, /* total length of the apdu */
|
||||
BACNET_READ_ACCESS_DATA * read_access_data)
|
||||
{
|
||||
int decoded_len = 0; /* return value */
|
||||
int len = 0; /* number of bytes returned from decoding */
|
||||
int decoded_len = 0; /* return value */
|
||||
int len = 0; /* number of bytes returned from decoding */
|
||||
BACNET_READ_ACCESS_DATA *rpm_object;
|
||||
BACNET_READ_ACCESS_DATA *old_rpm_object;
|
||||
BACNET_PROPERTY_REFERENCE *rpm_property;
|
||||
@@ -60,9 +60,8 @@ static int rpm_ack_decode_service_request(
|
||||
rpm_object = read_access_data;
|
||||
old_rpm_object = rpm_object;
|
||||
while (rpm_object && apdu_len) {
|
||||
len = rpm_ack_decode_object_id(
|
||||
apdu, apdu_len,
|
||||
&rpm_object->object_type,
|
||||
len =
|
||||
rpm_ack_decode_object_id(apdu, apdu_len, &rpm_object->object_type,
|
||||
&rpm_object->object_instance);
|
||||
if (len <= 0) {
|
||||
old_rpm_object->next = NULL;
|
||||
@@ -76,9 +75,8 @@ static int rpm_ack_decode_service_request(
|
||||
rpm_object->listOfProperties = rpm_property;
|
||||
old_rpm_property = rpm_property;
|
||||
while (rpm_property && apdu_len) {
|
||||
len = rpm_ack_decode_object_property(
|
||||
apdu,
|
||||
apdu_len,
|
||||
len =
|
||||
rpm_ack_decode_object_property(apdu, apdu_len,
|
||||
&rpm_property->propertyIdentifier,
|
||||
&rpm_property->propertyArrayIndex);
|
||||
if (len <= 0) {
|
||||
@@ -94,15 +92,13 @@ static int rpm_ack_decode_service_request(
|
||||
apdu_len--;
|
||||
apdu++;
|
||||
/* note: if this is an array, there will be
|
||||
more than one element to decode */
|
||||
more than one element to decode */
|
||||
value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE));
|
||||
rpm_property->value = value;
|
||||
old_value = value;
|
||||
while (value && (apdu_len > 0)) {
|
||||
len = bacapp_decode_application_data(
|
||||
apdu,
|
||||
apdu_len,
|
||||
value);
|
||||
len =
|
||||
bacapp_decode_application_data(apdu, apdu_len, value);
|
||||
decoded_len += len;
|
||||
apdu_len -= len;
|
||||
apdu += len;
|
||||
@@ -113,7 +109,8 @@ static int rpm_ack_decode_service_request(
|
||||
break;
|
||||
} else {
|
||||
old_value = value;
|
||||
value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE));
|
||||
value =
|
||||
calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE));
|
||||
old_value->next = value;
|
||||
}
|
||||
}
|
||||
@@ -174,8 +171,7 @@ static void PrintReadPropertyMultipleData(
|
||||
}
|
||||
#endif
|
||||
while (value) {
|
||||
bacapp_print_value(stdout,
|
||||
value,
|
||||
bacapp_print_value(stdout, value,
|
||||
listOfProperties->propertyIdentifier);
|
||||
#if PRINT_ENABLED
|
||||
if (value->next) {
|
||||
@@ -205,19 +201,20 @@ void handler_read_property_multiple_ack(
|
||||
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
|
||||
{
|
||||
int len = 0;
|
||||
BACNET_READ_ACCESS_DATA * rpm_data;
|
||||
BACNET_READ_ACCESS_DATA * old_rpm_data;
|
||||
BACNET_READ_ACCESS_DATA *rpm_data;
|
||||
BACNET_READ_ACCESS_DATA *old_rpm_data;
|
||||
BACNET_PROPERTY_REFERENCE *rpm_property;
|
||||
BACNET_PROPERTY_REFERENCE *old_rpm_property;
|
||||
BACNET_APPLICATION_DATA_VALUE *value;
|
||||
BACNET_APPLICATION_DATA_VALUE *old_value;
|
||||
|
||||
(void) src;
|
||||
(void) service_data; /* we could use these... */
|
||||
(void) service_data; /* we could use these... */
|
||||
|
||||
rpm_data = calloc(1, sizeof(BACNET_READ_ACCESS_DATA));
|
||||
if (rpm_data) {
|
||||
len = rpm_ack_decode_service_request(service_request, service_len,
|
||||
len =
|
||||
rpm_ack_decode_service_request(service_request, service_len,
|
||||
rpm_data);
|
||||
}
|
||||
#if 1
|
||||
|
||||
@@ -1,85 +1,81 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "apdu.h"
|
||||
#include "npdu.h"
|
||||
#include "abort.h"
|
||||
/* special for this module */
|
||||
#include "cov.h"
|
||||
#include "bactext.h"
|
||||
|
||||
/* note: nothing is specified in BACnet about what to do with the
|
||||
information received from Unconfirmed COV Notifications. */
|
||||
void handler_ucov_notification(
|
||||
uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src)
|
||||
{
|
||||
BACNET_COV_DATA cov_data;
|
||||
BACNET_PROPERTY_VALUE property_value;
|
||||
int len = 0;
|
||||
|
||||
/* create linked list to store data if more
|
||||
than one property value is expected */
|
||||
property_value.next = NULL;
|
||||
cov_data.listOfValues = &property_value;
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "UCOV: Received Notification!\n");
|
||||
#endif
|
||||
/* decode the service request only */
|
||||
len = cov_notify_decode_service_request(
|
||||
service_request, service_len, &cov_data);
|
||||
#if PRINT_ENABLED
|
||||
if (len > 0) {
|
||||
fprintf(stderr, "UCOV: PID=%u ",
|
||||
cov_data.subscriberProcessIdentifier);
|
||||
fprintf(stderr, "instance=%u ",
|
||||
cov_data.initiatingDeviceIdentifier);
|
||||
fprintf(stderr, "%s %u ",
|
||||
bactext_object_type_name(
|
||||
cov_data.monitoredObjectIdentifier.type),
|
||||
cov_data.monitoredObjectIdentifier.instance);
|
||||
fprintf(stderr, "time remaining=%u seconds ",
|
||||
cov_data.timeRemaining);
|
||||
fprintf(stderr, "%s ",
|
||||
bactext_property_name(property_value.propertyIdentifier));
|
||||
if (property_value.propertyArrayIndex != BACNET_ARRAY_ALL) {
|
||||
fprintf(stderr, "%u ",
|
||||
property_value.propertyArrayIndex);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
} else {
|
||||
fprintf(stderr, "UCOV: Unable to decode service request!\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "apdu.h"
|
||||
#include "npdu.h"
|
||||
#include "abort.h"
|
||||
/* special for this module */
|
||||
#include "cov.h"
|
||||
#include "bactext.h"
|
||||
|
||||
/* note: nothing is specified in BACnet about what to do with the
|
||||
information received from Unconfirmed COV Notifications. */
|
||||
void handler_ucov_notification(
|
||||
uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src)
|
||||
{
|
||||
BACNET_COV_DATA cov_data;
|
||||
BACNET_PROPERTY_VALUE property_value;
|
||||
int len = 0;
|
||||
|
||||
/* create linked list to store data if more
|
||||
than one property value is expected */
|
||||
property_value.next = NULL;
|
||||
cov_data.listOfValues = &property_value;
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "UCOV: Received Notification!\n");
|
||||
#endif
|
||||
/* decode the service request only */
|
||||
len =
|
||||
cov_notify_decode_service_request(service_request, service_len,
|
||||
&cov_data);
|
||||
#if PRINT_ENABLED
|
||||
if (len > 0) {
|
||||
fprintf(stderr, "UCOV: PID=%u ", cov_data.subscriberProcessIdentifier);
|
||||
fprintf(stderr, "instance=%u ", cov_data.initiatingDeviceIdentifier);
|
||||
fprintf(stderr, "%s %u ",
|
||||
bactext_object_type_name(cov_data.monitoredObjectIdentifier.type),
|
||||
cov_data.monitoredObjectIdentifier.instance);
|
||||
fprintf(stderr, "time remaining=%u seconds ", cov_data.timeRemaining);
|
||||
fprintf(stderr, "%s ",
|
||||
bactext_property_name(property_value.propertyIdentifier));
|
||||
if (property_value.propertyArrayIndex != BACNET_ARRAY_ALL) {
|
||||
fprintf(stderr, "%u ", property_value.propertyArrayIndex);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
} else {
|
||||
fprintf(stderr, "UCOV: Unable to decode service request!\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,94 +1,93 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "address.h"
|
||||
#include "tsm.h"
|
||||
#include "dcc.h"
|
||||
#include "npdu.h"
|
||||
#include "apdu.h"
|
||||
#include "device.h"
|
||||
#include "datalink.h"
|
||||
#include "iam.h"
|
||||
/* some demo stuff needed */
|
||||
#include "handlers.h"
|
||||
|
||||
int iam_encode_pdu(
|
||||
uint8_t * buffer,
|
||||
BACNET_ADDRESS * dest,
|
||||
BACNET_NPDU_DATA * npdu_data)
|
||||
{
|
||||
int len = 0;
|
||||
int pdu_len = 0;
|
||||
|
||||
/* I-Am is a global broadcast */
|
||||
datalink_get_broadcast_address(dest);
|
||||
/* encode the NPDU portion of the packet */
|
||||
npdu_encode_npdu_data(npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&buffer[0], dest, NULL, npdu_data);
|
||||
/* encode the APDU portion of the packet */
|
||||
len =
|
||||
iam_encode_apdu(&buffer[pdu_len], Device_Object_Instance_Number(),
|
||||
MAX_APDU, SEGMENTATION_NONE, Device_Vendor_Identifier());
|
||||
pdu_len += len;
|
||||
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
void Send_I_Am(
|
||||
uint8_t * buffer)
|
||||
{
|
||||
int pdu_len = 0;
|
||||
BACNET_ADDRESS dest;
|
||||
int bytes_sent = 0;
|
||||
BACNET_NPDU_DATA npdu_data;
|
||||
|
||||
#if 0
|
||||
/* note: there is discussion in the BACnet committee
|
||||
that we should allow a device to reply with I-Am
|
||||
so that dynamic binding always work. If the DCC
|
||||
initiator loses the MAC address and routing info,
|
||||
they can never re-enable DCC because they can't
|
||||
find the device with WhoIs/I-Am */
|
||||
/* are we are forbidden to send? */
|
||||
if (!dcc_communication_enabled())
|
||||
return 0;
|
||||
#endif
|
||||
/* encode the data */
|
||||
pdu_len = iam_encode_pdu(buffer, &dest, &npdu_data);
|
||||
/* send data */
|
||||
bytes_sent = datalink_send_pdu(&dest, &npdu_data, &buffer[0], pdu_len);
|
||||
|
||||
#if PRINT_ENABLED
|
||||
if (bytes_sent <= 0)
|
||||
fprintf(stderr, "Failed to Send I-Am Reply (%s)!\n",
|
||||
strerror(errno));
|
||||
#endif
|
||||
}
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2008 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include "config.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "address.h"
|
||||
#include "tsm.h"
|
||||
#include "dcc.h"
|
||||
#include "npdu.h"
|
||||
#include "apdu.h"
|
||||
#include "device.h"
|
||||
#include "datalink.h"
|
||||
#include "iam.h"
|
||||
/* some demo stuff needed */
|
||||
#include "handlers.h"
|
||||
|
||||
int iam_encode_pdu(
|
||||
uint8_t * buffer,
|
||||
BACNET_ADDRESS * dest,
|
||||
BACNET_NPDU_DATA * npdu_data)
|
||||
{
|
||||
int len = 0;
|
||||
int pdu_len = 0;
|
||||
|
||||
/* I-Am is a global broadcast */
|
||||
datalink_get_broadcast_address(dest);
|
||||
/* encode the NPDU portion of the packet */
|
||||
npdu_encode_npdu_data(npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len = npdu_encode_pdu(&buffer[0], dest, NULL, npdu_data);
|
||||
/* encode the APDU portion of the packet */
|
||||
len =
|
||||
iam_encode_apdu(&buffer[pdu_len], Device_Object_Instance_Number(),
|
||||
MAX_APDU, SEGMENTATION_NONE, Device_Vendor_Identifier());
|
||||
pdu_len += len;
|
||||
|
||||
return pdu_len;
|
||||
}
|
||||
|
||||
void Send_I_Am(
|
||||
uint8_t * buffer)
|
||||
{
|
||||
int pdu_len = 0;
|
||||
BACNET_ADDRESS dest;
|
||||
int bytes_sent = 0;
|
||||
BACNET_NPDU_DATA npdu_data;
|
||||
|
||||
#if 0
|
||||
/* note: there is discussion in the BACnet committee
|
||||
that we should allow a device to reply with I-Am
|
||||
so that dynamic binding always work. If the DCC
|
||||
initiator loses the MAC address and routing info,
|
||||
they can never re-enable DCC because they can't
|
||||
find the device with WhoIs/I-Am */
|
||||
/* are we are forbidden to send? */
|
||||
if (!dcc_communication_enabled())
|
||||
return 0;
|
||||
#endif
|
||||
/* encode the data */
|
||||
pdu_len = iam_encode_pdu(buffer, &dest, &npdu_data);
|
||||
/* send data */
|
||||
bytes_sent = datalink_send_pdu(&dest, &npdu_data, &buffer[0], pdu_len);
|
||||
|
||||
#if PRINT_ENABLED
|
||||
if (bytes_sent <= 0)
|
||||
fprintf(stderr, "Failed to Send I-Am Reply (%s)!\n", strerror(errno));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -69,8 +69,7 @@ void Send_Who_Is_Router_To_Network(
|
||||
BACNET_NPDU_DATA npdu_data;
|
||||
|
||||
npdu_encode_npdu_network(&npdu_data,
|
||||
NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK,
|
||||
false,
|
||||
NETWORK_MESSAGE_WHO_IS_ROUTER_TO_NETWORK, false,
|
||||
MESSAGE_PRIORITY_NORMAL);
|
||||
/* fixme: should dnet/dlen/dadr be set in NPDU? */
|
||||
pdu_len =
|
||||
@@ -112,8 +111,7 @@ void Send_I_Am_Router_To_Network(
|
||||
unsigned index = 0;
|
||||
|
||||
npdu_encode_npdu_network(&npdu_data,
|
||||
NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK,
|
||||
false,
|
||||
NETWORK_MESSAGE_I_AM_ROUTER_TO_NETWORK, false,
|
||||
MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len =
|
||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], NULL, NULL, &npdu_data);
|
||||
@@ -157,9 +155,7 @@ void Send_Initialize_Routing_Table(
|
||||
BACNET_ROUTER_PORT *router_port;
|
||||
unsigned i = 0; /* counter */
|
||||
|
||||
npdu_encode_npdu_network(&npdu_data,
|
||||
NETWORK_MESSAGE_INIT_RT_TABLE,
|
||||
true,
|
||||
npdu_encode_npdu_network(&npdu_data, NETWORK_MESSAGE_INIT_RT_TABLE, true,
|
||||
MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len =
|
||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], NULL, NULL, &npdu_data);
|
||||
@@ -208,10 +204,8 @@ void Send_Initialize_Routing_Table_Ack(
|
||||
int bytes_sent = 0;
|
||||
BACNET_NPDU_DATA npdu_data;
|
||||
|
||||
npdu_encode_npdu_network(&npdu_data,
|
||||
NETWORK_MESSAGE_INIT_RT_TABLE_ACK,
|
||||
false,
|
||||
MESSAGE_PRIORITY_NORMAL);
|
||||
npdu_encode_npdu_network(&npdu_data, NETWORK_MESSAGE_INIT_RT_TABLE_ACK,
|
||||
false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len =
|
||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], NULL, NULL, &npdu_data);
|
||||
/* encode the optional DNET list portion of the packet */
|
||||
|
||||
@@ -48,7 +48,7 @@ uint8_t Send_Read_Property_Multiple_Request(
|
||||
uint8_t * pdu,
|
||||
size_t max_pdu,
|
||||
uint32_t device_id, /* destination device */
|
||||
BACNET_READ_ACCESS_DATA *read_access_data)
|
||||
BACNET_READ_ACCESS_DATA * read_access_data)
|
||||
{
|
||||
BACNET_ADDRESS dest;
|
||||
BACNET_ADDRESS my_address;
|
||||
@@ -72,14 +72,10 @@ uint8_t Send_Read_Property_Multiple_Request(
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, true, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len =
|
||||
npdu_encode_pdu(&pdu[0], &dest, &my_address,
|
||||
&npdu_data);
|
||||
pdu_len = npdu_encode_pdu(&pdu[0], &dest, &my_address, &npdu_data);
|
||||
/* encode the APDU portion of the packet */
|
||||
len = rpm_encode_apdu(
|
||||
&pdu[pdu_len],
|
||||
max_pdu - pdu_len,
|
||||
invoke_id,
|
||||
len =
|
||||
rpm_encode_apdu(&pdu[pdu_len], max_pdu - pdu_len, invoke_id,
|
||||
read_access_data);
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
@@ -94,8 +90,7 @@ uint8_t Send_Read_Property_Multiple_Request(
|
||||
tsm_set_confirmed_unsegmented_transaction(invoke_id, &dest,
|
||||
&npdu_data, &pdu[0], (uint16_t) pdu_len);
|
||||
bytes_sent =
|
||||
datalink_send_pdu(&dest, &npdu_data,
|
||||
&pdu[0], pdu_len);
|
||||
datalink_send_pdu(&dest, &npdu_data, &pdu[0], pdu_len);
|
||||
#if PRINT_ENABLED
|
||||
if (bytes_sent <= 0)
|
||||
fprintf(stderr,
|
||||
|
||||
@@ -86,9 +86,9 @@ static void MyRejectHandler(
|
||||
}
|
||||
|
||||
static void My_Router_Handler(
|
||||
BACNET_ADDRESS *src,
|
||||
BACNET_NPDU_DATA *npdu_data,
|
||||
uint8_t * npdu, /* PDU data */
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_NPDU_DATA * npdu_data,
|
||||
uint8_t * npdu, /* PDU data */
|
||||
uint16_t npdu_len)
|
||||
{
|
||||
uint16_t npdu_offset = 0;
|
||||
@@ -122,26 +122,26 @@ static void My_Router_Handler(
|
||||
}
|
||||
}
|
||||
port_mappings = npdu[0];
|
||||
printf("\nPort Mappings: %u\n",port_mappings);
|
||||
printf("\nPort Mappings: %u\n", port_mappings);
|
||||
npdu_offset = 1;
|
||||
npdu_len--;
|
||||
while (npdu_len) {
|
||||
len = decode_unsigned16(&npdu[npdu_offset], &dnet);
|
||||
printf("DNET=%hu, ",dnet);
|
||||
printf("DNET=%hu, ", dnet);
|
||||
npdu_offset += len;
|
||||
npdu_len -= len;
|
||||
if (!npdu_len) {
|
||||
break;
|
||||
}
|
||||
port_id = npdu[npdu_offset];
|
||||
printf("Port ID=%u, ",port_id);
|
||||
printf("Port ID=%u, ", port_id);
|
||||
npdu_offset++;
|
||||
npdu_len--;
|
||||
if (!npdu_len) {
|
||||
break;
|
||||
}
|
||||
port_info_len = npdu[npdu_offset];
|
||||
printf("Port Info Length=%u, ",port_info_len);
|
||||
printf("Port Info Length=%u, ", port_info_len);
|
||||
npdu_offset++;
|
||||
npdu_len--;
|
||||
printf("Port Info=\"");
|
||||
@@ -150,7 +150,7 @@ static void My_Router_Handler(
|
||||
break;
|
||||
}
|
||||
if (j < port_info_len) {
|
||||
printf("%02X",npdu[npdu_offset]);
|
||||
printf("%02X", npdu[npdu_offset]);
|
||||
npdu_offset++;
|
||||
npdu_len--;
|
||||
}
|
||||
@@ -182,7 +182,7 @@ static void My_NPDU_Handler(
|
||||
|
||||
apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data);
|
||||
if (npdu_data.network_layer_message) {
|
||||
My_Router_Handler(src,&npdu_data,&pdu[apdu_offset],
|
||||
My_Router_Handler(src, &npdu_data, &pdu[apdu_offset],
|
||||
(uint16_t) (pdu_len - apdu_offset));
|
||||
} else if ((apdu_offset > 0) && (apdu_offset <= pdu_len)) {
|
||||
if ((npdu_data.protocol_version == BACNET_PROTOCOL_VERSION) &&
|
||||
@@ -325,7 +325,8 @@ static void address_parse(BACNET_ADDRESS * dst,
|
||||
dst->mac_len = 6;
|
||||
for (index = 0; index < 4; index++) {
|
||||
dst->mac[index] = mac[index];
|
||||
} encode_unsigned16(&dst->mac[4],
|
||||
}
|
||||
encode_unsigned16(&dst->mac[4],
|
||||
port);
|
||||
} else {
|
||||
count =
|
||||
@@ -364,22 +365,14 @@ int main(int argc, char *argv[]) {
|
||||
filename_remove_path(argv[0]));
|
||||
return 0;
|
||||
}
|
||||
if ((
|
||||
argc > 1) && (
|
||||
strcmp(argv[1],
|
||||
"--help") == 0)) {
|
||||
if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
|
||||
printf("Send BACnet Initialize-Routing-Table message to a network\r\n"
|
||||
"and wait for responses. Displays their network information.\r\n"
|
||||
"\r\n"
|
||||
"address:\r\n"
|
||||
"\r\n" "address:\r\n"
|
||||
"MAC address in xx:xx:xx:xx:xx:xx format or IP x.x.x.x:port\r\n"
|
||||
"DNET ID Len Info:\r\n"
|
||||
"Port-info data:\r\n"
|
||||
" DNET:\r\n"
|
||||
" Destination network number 0-65534\r\n"
|
||||
" ID:\r\n"
|
||||
" Port Identifier number 0-255\r\n"
|
||||
" Info:\r\n"
|
||||
"DNET ID Len Info:\r\n" "Port-info data:\r\n" " DNET:\r\n"
|
||||
" Destination network number 0-65534\r\n" " ID:\r\n"
|
||||
" Port Identifier number 0-255\r\n" " Info:\r\n"
|
||||
" Octet string of data, up to 255 octets\r\n"
|
||||
"To query the complete routing table, do not include any port-info.\r\n"
|
||||
"To query using Initialize-Routing-Table message to 192.168.0.18:\r\n"
|
||||
|
||||
@@ -139,7 +139,7 @@ static void milliseconds_task_win32(
|
||||
|
||||
/* functions used by the MS/TP state machine to put or get data */
|
||||
uint16_t MSTP_Put_Receive(
|
||||
volatile struct mstp_port_struct_t * mstp_port)
|
||||
volatile struct mstp_port_struct_t *mstp_port)
|
||||
{
|
||||
(void) mstp_port;
|
||||
|
||||
@@ -217,7 +217,7 @@ static void write_received_packet(
|
||||
fwrite(&ts_sec, sizeof(ts_sec), 1, pFile);
|
||||
fwrite(&ts_usec, sizeof(ts_usec), 1, pFile);
|
||||
if (mstp_port->DataLength) {
|
||||
max_data = min(mstp_port->InputBufferSize,mstp_port->DataLength);
|
||||
max_data = min(mstp_port->InputBufferSize, mstp_port->DataLength);
|
||||
incl_len = orig_len = 8 + max_data + 2;
|
||||
} else {
|
||||
incl_len = orig_len = 8;
|
||||
|
||||
@@ -308,12 +308,12 @@ int Binary_Output_Encode_Property_APDU(
|
||||
apdu_len = encode_application_enumerated(&apdu[0], present_value);
|
||||
break;
|
||||
case PROP_ACTIVE_TEXT:
|
||||
characterstring_init_ansi(&char_string,"on" );
|
||||
characterstring_init_ansi(&char_string, "on");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_INACTIVE_TEXT:
|
||||
characterstring_init_ansi(&char_string,"off" );
|
||||
characterstring_init_ansi(&char_string, "off");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
|
||||
@@ -216,23 +216,21 @@ static void Init_DataLink(
|
||||
#endif
|
||||
}
|
||||
|
||||
void cleanup(void)
|
||||
{
|
||||
void cleanup(void) {
|
||||
BACNET_READ_ACCESS_DATA *rpm_object;
|
||||
BACNET_READ_ACCESS_DATA *old_rpm_object;
|
||||
BACNET_PROPERTY_REFERENCE *rpm_property;
|
||||
BACNET_PROPERTY_REFERENCE *old_rpm_property;
|
||||
|
||||
rpm_object = Read_Access_Data;
|
||||
old_rpm_object = rpm_object;
|
||||
while (rpm_object) {
|
||||
rpm_object = Read_Access_Data;
|
||||
old_rpm_object = rpm_object;
|
||||
while (rpm_object) {
|
||||
rpm_property = rpm_object->listOfProperties;
|
||||
while (rpm_property) {
|
||||
old_rpm_property = rpm_property;
|
||||
rpm_property = rpm_property->next;
|
||||
free(old_rpm_property);
|
||||
}
|
||||
old_rpm_object = rpm_object;
|
||||
} old_rpm_object = rpm_object;
|
||||
rpm_object = rpm_object->next;
|
||||
free(old_rpm_object);
|
||||
}
|
||||
@@ -251,14 +249,16 @@ int main(int argc, char *argv[]) {
|
||||
time_t timeout_seconds = 0;
|
||||
uint8_t invoke_id = 0;
|
||||
bool found = false;
|
||||
uint8_t buffer[MAX_PDU] = {0};
|
||||
uint8_t buffer[MAX_PDU] = {
|
||||
0};
|
||||
BACNET_READ_ACCESS_DATA *rpm_object;
|
||||
BACNET_PROPERTY_REFERENCE *rpm_property;
|
||||
|
||||
|
||||
if (argc < 5) {
|
||||
printf("Usage: %s device-instance object-type object-instance "
|
||||
"property index [object-type ...]\r\n", filename_remove_path(argv[0]));
|
||||
"property index [object-type ...]\r\n",
|
||||
filename_remove_path(argv[0]));
|
||||
if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
|
||||
printf("device-instance:\r\n"
|
||||
"BACnet Device Object Instance number that you are\r\n"
|
||||
@@ -285,8 +285,7 @@ int main(int argc, char *argv[]) {
|
||||
"If the property is an array, individual elements can\r\n"
|
||||
"be read. If this parameter is missing and the property\r\n"
|
||||
"is an array, the entire array will be read.\r\n"
|
||||
"\r\nExample:\r\n"
|
||||
"If you want read the ALL property in\r\n"
|
||||
"\r\nExample:\r\n" "If you want read the ALL property in\r\n"
|
||||
"Device object 123, you would use the following command:\r\n"
|
||||
"%s 123 8 123 8 -1\r\n"
|
||||
"If you want read the OPTIONAL property in\r\n"
|
||||
@@ -294,10 +293,8 @@ int main(int argc, char *argv[]) {
|
||||
"%s 123 8 123 80 -1\r\n"
|
||||
"If you want read the REQUIRED property in\r\n"
|
||||
"Device object 123, you would use the following command:\r\n"
|
||||
"%s 123 8 123 105 -1\r\n",
|
||||
filename_remove_path(argv[0]),
|
||||
filename_remove_path(argv[0]),
|
||||
filename_remove_path(argv[0]));
|
||||
"%s 123 8 123 105 -1\r\n", filename_remove_path(argv[0]),
|
||||
filename_remove_path(argv[0]), filename_remove_path(argv[0]));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -315,8 +312,7 @@ int main(int argc, char *argv[]) {
|
||||
arg_sets = 0;
|
||||
while (rpm_object) {
|
||||
tag_value_arg = 2 + (arg_sets * 4);
|
||||
rpm_object->object_type =
|
||||
strtol(argv[tag_value_arg], NULL, 0);
|
||||
rpm_object->object_type = strtol(argv[tag_value_arg], NULL, 0);
|
||||
tag_value_arg++;
|
||||
args_remaining--;
|
||||
if (args_remaining <= 0) {
|
||||
@@ -328,8 +324,7 @@ int main(int argc, char *argv[]) {
|
||||
rpm_object->object_type, MAX_BACNET_OBJECT_TYPE + 1);
|
||||
return 1;
|
||||
}
|
||||
rpm_object->object_instance =
|
||||
strtol(argv[tag_value_arg], NULL, 0);
|
||||
rpm_object->object_instance = strtol(argv[tag_value_arg], NULL, 0);
|
||||
tag_value_arg++;
|
||||
args_remaining--;
|
||||
if (args_remaining <= 0) {
|
||||
@@ -350,12 +345,14 @@ int main(int argc, char *argv[]) {
|
||||
tag_value_arg++;
|
||||
args_remaining--;
|
||||
if (args_remaining <= 0) {
|
||||
fprintf(stderr, "Error: not enough object property quads.\r\n");
|
||||
fprintf(stderr,
|
||||
"Error: not enough object property quads.\r\n");
|
||||
return 1;
|
||||
}
|
||||
if (rpm_property->propertyIdentifier > MAX_BACNET_PROPERTY_ID) {
|
||||
fprintf(stderr, "property=%u - it must be less than %u\r\n",
|
||||
rpm_property->propertyIdentifier, MAX_BACNET_PROPERTY_ID + 1);
|
||||
rpm_property->propertyIdentifier,
|
||||
MAX_BACNET_PROPERTY_ID + 1);
|
||||
return 1;
|
||||
}
|
||||
rpm_property->propertyArrayIndex =
|
||||
@@ -413,10 +410,9 @@ int main(int argc, char *argv[]) {
|
||||
&Target_Address);
|
||||
if (found) {
|
||||
if (invoke_id == 0) {
|
||||
invoke_id = Send_Read_Property_Multiple_Request(
|
||||
&buffer[0],
|
||||
sizeof(buffer),
|
||||
Target_Device_Object_Instance,
|
||||
invoke_id =
|
||||
Send_Read_Property_Multiple_Request(&buffer[0],
|
||||
sizeof(buffer), Target_Device_Object_Instance,
|
||||
Read_Access_Data);
|
||||
} else if (tsm_invoke_id_free(invoke_id))
|
||||
break;
|
||||
|
||||
@@ -87,7 +87,7 @@ static void Init_Service_Handlers(
|
||||
handler_timesync);
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_SUBSCRIBE_COV,
|
||||
handler_cov_subscribe);
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_COV_NOTIFICATION,
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_COV_NOTIFICATION,
|
||||
handler_ucov_notification);
|
||||
/* handle communication so we can shutup when asked */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
|
||||
|
||||
@@ -212,8 +212,8 @@ int main(int argc, char *argv[]) {
|
||||
filename_remove_path(argv[0]), filename_remove_path(argv[0]));
|
||||
return 0;
|
||||
}
|
||||
/* decode the command line parameters */
|
||||
cov_data.subscriberProcessIdentifier = strtol(argv[1], NULL, 0);
|
||||
/* decode the command line parameters */ cov_data.
|
||||
subscriberProcessIdentifier = strtol(argv[1], NULL, 0);
|
||||
cov_data.initiatingDeviceIdentifier = strtol(argv[2], NULL, 0);
|
||||
cov_data.monitoredObjectIdentifier.type = strtol(argv[3], NULL, 0);
|
||||
cov_data.monitoredObjectIdentifier.instance = strtol(argv[4], NULL, 0);
|
||||
|
||||
@@ -87,7 +87,7 @@ static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
/* Note: this applications doesn't need to handle who-is
|
||||
it is confusing for the user! */
|
||||
it is confusing for the user! */
|
||||
/* 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
|
||||
|
||||
@@ -86,9 +86,9 @@ static void MyRejectHandler(
|
||||
}
|
||||
|
||||
static void My_Router_Handler(
|
||||
BACNET_ADDRESS *src,
|
||||
BACNET_NPDU_DATA *npdu_data,
|
||||
uint8_t * npdu, /* PDU data */
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_NPDU_DATA * npdu_data,
|
||||
uint8_t * npdu, /* PDU data */
|
||||
uint16_t npdu_len)
|
||||
{
|
||||
uint16_t npdu_offset = 0;
|
||||
@@ -109,7 +109,7 @@ static void My_Router_Handler(
|
||||
printf("\nNetworks: ");
|
||||
while (npdu_len) {
|
||||
len = decode_unsigned16(&npdu[npdu_offset], &dnet);
|
||||
printf("%hu",dnet);
|
||||
printf("%hu", dnet);
|
||||
npdu_len -= len;
|
||||
if (npdu_len) {
|
||||
printf(", ");
|
||||
@@ -141,7 +141,7 @@ void My_NPDU_Handler(
|
||||
|
||||
apdu_offset = npdu_decode(&pdu[0], &dest, src, &npdu_data);
|
||||
if (npdu_data.network_layer_message) {
|
||||
My_Router_Handler(src,&npdu_data,&pdu[apdu_offset],
|
||||
My_Router_Handler(src, &npdu_data, &pdu[apdu_offset],
|
||||
(uint16_t) (pdu_len - apdu_offset));
|
||||
} else if ((apdu_offset > 0) && (apdu_offset <= pdu_len)) {
|
||||
if ((npdu_data.protocol_version == BACNET_PROTOCOL_VERSION) &&
|
||||
|
||||
@@ -112,10 +112,10 @@ extern "C" {
|
||||
bool decode_context_boolean(
|
||||
uint8_t * apdu);
|
||||
|
||||
int decode_context_boolean2(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
bool *boolean_value);
|
||||
int decode_context_boolean2(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
bool * boolean_value);
|
||||
|
||||
/* from clause 20.2.10 Encoding of a Bit String Value */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
@@ -126,7 +126,7 @@ extern "C" {
|
||||
|
||||
int decode_context_bitstring(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
uint8_t tag_number,
|
||||
BACNET_BIT_STRING * bit_string);
|
||||
/* returns the number of apdu bytes consumed */
|
||||
int encode_bitstring(
|
||||
@@ -154,15 +154,15 @@ extern "C" {
|
||||
/* from clause 20.2.7 Encoding of a Double Precision Real Number Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
int encode_application_double(
|
||||
uint8_t * apdu,
|
||||
double value);
|
||||
|
||||
int encode_context_double(
|
||||
uint8_t * apdu,
|
||||
int tag_number,
|
||||
double value);
|
||||
|
||||
int encode_application_double(
|
||||
uint8_t * apdu,
|
||||
double value);
|
||||
|
||||
int encode_context_double(
|
||||
uint8_t * apdu,
|
||||
int tag_number,
|
||||
double value);
|
||||
|
||||
/* from clause 20.2.14 Encoding of an Object Identifier Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
@@ -171,11 +171,11 @@ int encode_context_double(
|
||||
uint16_t * object_type,
|
||||
uint32_t * instance);
|
||||
|
||||
int decode_context_object_id(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
uint16_t *object_type,
|
||||
uint32_t * instance);
|
||||
int decode_context_object_id(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
uint16_t * object_type,
|
||||
uint32_t * instance);
|
||||
|
||||
int encode_bacnet_object_id(
|
||||
uint8_t * apdu,
|
||||
@@ -210,7 +210,7 @@ int encode_context_double(
|
||||
BACNET_OCTET_STRING * octet_string);
|
||||
int decode_context_octet_string(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
uint8_t tag_number,
|
||||
BACNET_OCTET_STRING * octet_string);
|
||||
|
||||
|
||||
@@ -231,10 +231,10 @@ int encode_context_double(
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
BACNET_CHARACTER_STRING * char_string);
|
||||
int decode_context_character_string(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_CHARACTER_STRING * char_string);
|
||||
int decode_context_character_string(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_CHARACTER_STRING * char_string);
|
||||
|
||||
|
||||
/* from clause 20.2.4 Encoding of an Unsigned Integer Value */
|
||||
@@ -254,10 +254,10 @@ int encode_context_double(
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
uint32_t * value);
|
||||
int decode_context_unsigned(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
uint32_t * value);
|
||||
int decode_context_unsigned(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
uint32_t * value);
|
||||
|
||||
/* from clause 20.2.5 Encoding of a Signed Integer Value */
|
||||
/* and 20.2.1 General Rules for Encoding BACnet Tags */
|
||||
@@ -276,10 +276,10 @@ int encode_context_double(
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
int32_t * value);
|
||||
int decode_context_signed(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
int32_t * value);
|
||||
int decode_context_signed(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
int32_t * value);
|
||||
|
||||
|
||||
/* from clause 20.2.11 Encoding of an Enumerated Value */
|
||||
@@ -289,10 +289,10 @@ int encode_context_double(
|
||||
uint8_t * apdu,
|
||||
uint32_t len_value,
|
||||
int *value);
|
||||
int decode_context_enumerated(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_value,
|
||||
int *value);
|
||||
int decode_context_enumerated(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_value,
|
||||
int *value);
|
||||
int encode_bacnet_enumerated(
|
||||
uint8_t * apdu,
|
||||
int value);
|
||||
@@ -320,13 +320,13 @@ int encode_context_double(
|
||||
uint8_t * apdu,
|
||||
int tag_number,
|
||||
BACNET_TIME * btime);
|
||||
int decode_application_time(
|
||||
uint8_t * apdu,
|
||||
BACNET_TIME * btime);
|
||||
int decode_context_bacnet_time(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIME * btime);
|
||||
int decode_application_time(
|
||||
uint8_t * apdu,
|
||||
BACNET_TIME * btime);
|
||||
int decode_context_bacnet_time(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIME * btime);
|
||||
|
||||
|
||||
/* BACnet Date */
|
||||
@@ -354,10 +354,10 @@ int encode_context_double(
|
||||
int decode_application_date(
|
||||
uint8_t * apdu,
|
||||
BACNET_DATE * bdate);
|
||||
int decode_context_date(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE * bdate);
|
||||
int decode_context_date(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE * bdate);
|
||||
|
||||
/* from clause 20.1.2.4 max-segments-accepted */
|
||||
/* and clause 20.1.2.5 max-APDU-length-accepted */
|
||||
|
||||
@@ -1,75 +1,72 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#ifndef _BAC_DEV_PROP_REF_H_
|
||||
#define _BAC_DEV_PROP_REF_H_
|
||||
|
||||
|
||||
typedef struct {
|
||||
BACNET_OBJECT_ID objectIdentifier;
|
||||
BACNET_PROPERTY_ID propertyIdentifier;
|
||||
uint32_t arrayIndex;
|
||||
BACNET_OBJECT_ID deviceIndentifier;
|
||||
} BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int bacapp_encode_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value);
|
||||
|
||||
int bacapp_encode_context_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value);
|
||||
|
||||
int bacapp_decode_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value);
|
||||
|
||||
int bacapp_decode_context_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif //_BAC_DEV_PROP_REF_H_
|
||||
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#ifndef _BAC_DEV_PROP_REF_H_
|
||||
#define _BAC_DEV_PROP_REF_H_
|
||||
|
||||
|
||||
typedef struct {
|
||||
BACNET_OBJECT_ID objectIdentifier;
|
||||
BACNET_PROPERTY_ID propertyIdentifier;
|
||||
uint32_t arrayIndex;
|
||||
BACNET_OBJECT_ID deviceIndentifier;
|
||||
} BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int bacapp_encode_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value);
|
||||
|
||||
int bacapp_encode_context_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value);
|
||||
|
||||
int bacapp_decode_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value);
|
||||
|
||||
int bacapp_decode_context_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif //_BAC_DEV_PROP_REF_H_
|
||||
|
||||
@@ -1,104 +1,102 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#ifndef _BAC_PROP_STATES_H_
|
||||
#define _BAC_PROP_STATES_H_
|
||||
|
||||
#include "bacenum.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "bacapp.h"
|
||||
#include <time.h>
|
||||
#include "timestamp.h"
|
||||
|
||||
typedef enum {
|
||||
BOOLEAN_VALUE,
|
||||
BINARY_VALUE,
|
||||
EVENT_TYPE,
|
||||
POLARITY,
|
||||
PROGRAM_CHANGE,
|
||||
PROGRAM_STATE,
|
||||
REASON_FOR_HALT,
|
||||
RELIABILITY,
|
||||
STATE,
|
||||
SYSTEM_STATUS,
|
||||
UNITS,
|
||||
UNSIGNED_VALUE,
|
||||
LIFE_SAFETY_MODE,
|
||||
LIFE_SAFETY_STATE,
|
||||
} BACNET_PROPERTY_STATE_TYPE;
|
||||
|
||||
typedef struct {
|
||||
BACNET_PROPERTY_STATE_TYPE tag;
|
||||
union {
|
||||
bool booleanValue;
|
||||
BACNET_BINARY_PV binaryValue;
|
||||
BACNET_EVENT_TYPE eventType;
|
||||
BACNET_POLARITY polarity;
|
||||
BACNET_PROGRAM_REQUEST programChange;
|
||||
BACNET_PROGRAM_STATE programState;
|
||||
BACNET_PROGRAM_ERROR programError;
|
||||
BACNET_RELIABILITY reliability;
|
||||
BACNET_EVENT_STATE state;
|
||||
BACNET_DEVICE_STATUS systemStatus;
|
||||
BACNET_ENGINEERING_UNITS units;
|
||||
uint32_t unsignedValue;
|
||||
BACNET_LIFE_SAFETY_MODE lifeSafetyMode;
|
||||
BACNET_LIFE_SAFETY_STATE lifeSafetyState;
|
||||
} state;
|
||||
} BACNET_PROPERTY_STATE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int bacapp_decode_property_state(
|
||||
uint8_t * apdu,
|
||||
BACNET_PROPERTY_STATE * value);
|
||||
|
||||
int bacapp_decode_context_property_state(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_PROPERTY_STATE * value);
|
||||
|
||||
int bacapp_encode_property_state(
|
||||
uint8_t * apdu,
|
||||
BACNET_PROPERTY_STATE * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif // _BAC_PROP_STATES_H_
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#ifndef _BAC_PROP_STATES_H_
|
||||
#define _BAC_PROP_STATES_H_
|
||||
|
||||
#include "bacenum.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "bacapp.h"
|
||||
#include <time.h>
|
||||
#include "timestamp.h"
|
||||
|
||||
typedef enum {
|
||||
BOOLEAN_VALUE,
|
||||
BINARY_VALUE,
|
||||
EVENT_TYPE,
|
||||
POLARITY,
|
||||
PROGRAM_CHANGE,
|
||||
PROGRAM_STATE,
|
||||
REASON_FOR_HALT,
|
||||
RELIABILITY,
|
||||
STATE,
|
||||
SYSTEM_STATUS,
|
||||
UNITS,
|
||||
UNSIGNED_VALUE,
|
||||
LIFE_SAFETY_MODE,
|
||||
LIFE_SAFETY_STATE,
|
||||
} BACNET_PROPERTY_STATE_TYPE;
|
||||
|
||||
typedef struct {
|
||||
BACNET_PROPERTY_STATE_TYPE tag;
|
||||
union {
|
||||
bool booleanValue;
|
||||
BACNET_BINARY_PV binaryValue;
|
||||
BACNET_EVENT_TYPE eventType;
|
||||
BACNET_POLARITY polarity;
|
||||
BACNET_PROGRAM_REQUEST programChange;
|
||||
BACNET_PROGRAM_STATE programState;
|
||||
BACNET_PROGRAM_ERROR programError;
|
||||
BACNET_RELIABILITY reliability;
|
||||
BACNET_EVENT_STATE state;
|
||||
BACNET_DEVICE_STATUS systemStatus;
|
||||
BACNET_ENGINEERING_UNITS units;
|
||||
uint32_t unsignedValue;
|
||||
BACNET_LIFE_SAFETY_MODE lifeSafetyMode;
|
||||
BACNET_LIFE_SAFETY_STATE lifeSafetyState;
|
||||
} state;
|
||||
} BACNET_PROPERTY_STATE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
int bacapp_decode_property_state(
|
||||
uint8_t * apdu,
|
||||
BACNET_PROPERTY_STATE * value);
|
||||
|
||||
int bacapp_decode_context_property_state(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_PROPERTY_STATE * value);
|
||||
|
||||
int bacapp_encode_property_state(
|
||||
uint8_t * apdu,
|
||||
BACNET_PROPERTY_STATE * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif // _BAC_PROP_STATES_H_
|
||||
|
||||
@@ -48,7 +48,7 @@ extern "C" {
|
||||
|
||||
int decode_context_real(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
uint8_t tag_number,
|
||||
float *real_value);
|
||||
int encode_bacnet_real(
|
||||
float value,
|
||||
|
||||
@@ -78,8 +78,8 @@ extern "C" {
|
||||
uint8_t Send_Read_Property_Multiple_Request(
|
||||
uint8_t * pdu,
|
||||
size_t max_pdu,
|
||||
uint32_t device_id, /* destination device */
|
||||
BACNET_READ_ACCESS_DATA *read_access_data);
|
||||
uint32_t device_id, /* destination device */
|
||||
BACNET_READ_ACCESS_DATA * read_access_data);
|
||||
|
||||
/* returns the invoke ID for confirmed request, or 0 if failed */
|
||||
uint8_t Send_Write_Property_Request(
|
||||
|
||||
@@ -138,19 +138,19 @@ extern "C" {
|
||||
void datetime_time_wildcard_set(
|
||||
BACNET_TIME * btime);
|
||||
|
||||
int bacapp_encode_context_datetime(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE_TIME * value);
|
||||
int bacapp_encode_context_datetime(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE_TIME * value);
|
||||
|
||||
int bacapp_decode_datetime(
|
||||
uint8_t * apdu,
|
||||
BACNET_DATE_TIME * value);
|
||||
int bacapp_decode_datetime(
|
||||
uint8_t * apdu,
|
||||
BACNET_DATE_TIME * value);
|
||||
|
||||
int bacapp_decode_context_datetime(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE_TIME * value);
|
||||
int bacapp_decode_context_datetime(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE_TIME * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -38,26 +38,23 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include "bacdef.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#if DEBUG_ENABLED
|
||||
void debug_printf(
|
||||
const char *format,
|
||||
...);
|
||||
void debug_printf(
|
||||
const char *format,
|
||||
...);
|
||||
#else
|
||||
static void debug_printf(
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
format = format;
|
||||
static void debug_printf(
|
||||
const char *format,
|
||||
...) {
|
||||
format = format;
|
||||
}
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
|
||||
+212
-212
@@ -1,212 +1,212 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#ifndef BACNET_EVENT_H_
|
||||
#define BACNET_EVENT_H_
|
||||
|
||||
#include "bacenum.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "bacapp.h"
|
||||
#include "timestamp.h"
|
||||
#include "bacpropstates.h"
|
||||
#include "bacdevobjpropref.h"
|
||||
|
||||
typedef enum {
|
||||
CHANGE_OF_VALUE_BITS,
|
||||
CHANGE_OF_VALUE_REAL
|
||||
} CHANGE_OF_VALUE_TYPE;
|
||||
|
||||
/*
|
||||
** Based on UnconfirmedEventNotification-Request
|
||||
*/
|
||||
|
||||
typedef struct BACnet_Event_Notification_Data {
|
||||
uint32_t processIdentifier;
|
||||
BACNET_OBJECT_ID initiatingObjectIdentifier;
|
||||
BACNET_OBJECT_ID eventObjectIdentifier;
|
||||
BACNET_TIMESTAMP timeStamp;
|
||||
uint32_t notificationClass;
|
||||
uint8_t priority;
|
||||
BACNET_EVENT_TYPE eventType;
|
||||
BACNET_CHARACTER_STRING* messageText; /* OPTIONAL - Set to NULL if not being used */
|
||||
BACNET_NOTIFY_TYPE notifyType;
|
||||
bool ackRequired;
|
||||
BACNET_EVENT_STATE fromState;
|
||||
BACNET_EVENT_STATE toState;
|
||||
/*
|
||||
** Each of these structures in the union maps to a particular eventtype
|
||||
** Based on BACnetNotificationParameters
|
||||
*/
|
||||
|
||||
union {
|
||||
/*
|
||||
** EVENT_CHANGE_OF_BITSTRING
|
||||
*/
|
||||
struct {
|
||||
BACNET_BIT_STRING referencedBitString;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
} changeOfBitstring;
|
||||
/*
|
||||
** EVENT_CHANGE_OF_STATE
|
||||
*/
|
||||
struct {
|
||||
BACNET_PROPERTY_STATE newState;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
} changeOfState;
|
||||
/*
|
||||
** EVENT_CHANGE_OF_VALUE
|
||||
*/
|
||||
struct {
|
||||
union {
|
||||
BACNET_BIT_STRING changedBits;
|
||||
float changeValue;
|
||||
} newValue;
|
||||
CHANGE_OF_VALUE_TYPE tag;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
} changeOfValue;
|
||||
/*
|
||||
** EVENT_COMMAND_FAILURE
|
||||
**
|
||||
** Not Supported!
|
||||
*/
|
||||
/*
|
||||
** EVENT_FLOATING_LIMIT
|
||||
*/
|
||||
struct {
|
||||
float referenceValue;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
float setPointValue;
|
||||
float errorLimit;
|
||||
} floatingLimit;
|
||||
/*
|
||||
** EVENT_OUT_OF_RANGE
|
||||
*/
|
||||
struct {
|
||||
float exceedingValue;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
float deadband;
|
||||
float exceededLimit;
|
||||
} outOfRange;
|
||||
/*
|
||||
** EVENT_CHANGE_OF_LIFE_SAFETY
|
||||
*/
|
||||
struct {
|
||||
BACNET_LIFE_SAFETY_STATE newState;
|
||||
BACNET_LIFE_SAFETY_MODE newMode;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
BACNET_LIFE_SAFETY_OPERATION operationExpected;
|
||||
} changeOfLifeSafety;
|
||||
/*
|
||||
** EVENT_EXTENDED
|
||||
**
|
||||
** Not Supported!
|
||||
*/
|
||||
/*
|
||||
** EVENT_BUFFER_READY
|
||||
*/
|
||||
struct {
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE bufferProperty;
|
||||
uint32_t previousNotification;
|
||||
uint32_t currentNotification;
|
||||
} bufferReady;
|
||||
/*
|
||||
** EVENT_UNSIGNED_RANGE
|
||||
*/
|
||||
struct {
|
||||
uint32_t exceedingValue;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
uint32_t exceededLimit;
|
||||
} unsignedRange;
|
||||
} notificationParams;
|
||||
} BACNET_EVENT_NOTIFICATION_DATA;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Creates a Confirmed Event Notification APDU
|
||||
**
|
||||
****************************************************/
|
||||
int cevent_notify_encode_apdu(
|
||||
uint8_t * apdu,
|
||||
uint8_t invoke_id,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data);
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Creates an Unconfirmed Event Notification APDU
|
||||
**
|
||||
****************************************************/
|
||||
int uevent_notify_encode_apdu(
|
||||
uint8_t * apdu,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data);
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Encodes the service data part of Event Notification
|
||||
**
|
||||
****************************************************/
|
||||
int event_notify_encode_service_request(
|
||||
uint8_t * apdu,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data);
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Decodes the service data part of Event Notification
|
||||
**
|
||||
****************************************************/
|
||||
int event_notify_decode_service_request(
|
||||
uint8_t * apdu,
|
||||
unsigned apdu_len,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data);
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Sends an Unconfirmed Event Notifcation to a dest
|
||||
**
|
||||
****************************************************/
|
||||
int uevent_notify_send(
|
||||
uint8_t * buffer,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data,
|
||||
BACNET_ADDRESS *dest);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* BACNET_EVENT_H_ */
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#ifndef BACNET_EVENT_H_
|
||||
#define BACNET_EVENT_H_
|
||||
|
||||
#include "bacenum.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "bacapp.h"
|
||||
#include "timestamp.h"
|
||||
#include "bacpropstates.h"
|
||||
#include "bacdevobjpropref.h"
|
||||
|
||||
typedef enum {
|
||||
CHANGE_OF_VALUE_BITS,
|
||||
CHANGE_OF_VALUE_REAL
|
||||
} CHANGE_OF_VALUE_TYPE;
|
||||
|
||||
/*
|
||||
** Based on UnconfirmedEventNotification-Request
|
||||
*/
|
||||
|
||||
typedef struct BACnet_Event_Notification_Data {
|
||||
uint32_t processIdentifier;
|
||||
BACNET_OBJECT_ID initiatingObjectIdentifier;
|
||||
BACNET_OBJECT_ID eventObjectIdentifier;
|
||||
BACNET_TIMESTAMP timeStamp;
|
||||
uint32_t notificationClass;
|
||||
uint8_t priority;
|
||||
BACNET_EVENT_TYPE eventType;
|
||||
BACNET_CHARACTER_STRING *messageText; /* OPTIONAL - Set to NULL if not being used */
|
||||
BACNET_NOTIFY_TYPE notifyType;
|
||||
bool ackRequired;
|
||||
BACNET_EVENT_STATE fromState;
|
||||
BACNET_EVENT_STATE toState;
|
||||
/*
|
||||
** Each of these structures in the union maps to a particular eventtype
|
||||
** Based on BACnetNotificationParameters
|
||||
*/
|
||||
|
||||
union {
|
||||
/*
|
||||
** EVENT_CHANGE_OF_BITSTRING
|
||||
*/
|
||||
struct {
|
||||
BACNET_BIT_STRING referencedBitString;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
} changeOfBitstring;
|
||||
/*
|
||||
** EVENT_CHANGE_OF_STATE
|
||||
*/
|
||||
struct {
|
||||
BACNET_PROPERTY_STATE newState;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
} changeOfState;
|
||||
/*
|
||||
** EVENT_CHANGE_OF_VALUE
|
||||
*/
|
||||
struct {
|
||||
union {
|
||||
BACNET_BIT_STRING changedBits;
|
||||
float changeValue;
|
||||
} newValue;
|
||||
CHANGE_OF_VALUE_TYPE tag;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
} changeOfValue;
|
||||
/*
|
||||
** EVENT_COMMAND_FAILURE
|
||||
**
|
||||
** Not Supported!
|
||||
*/
|
||||
/*
|
||||
** EVENT_FLOATING_LIMIT
|
||||
*/
|
||||
struct {
|
||||
float referenceValue;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
float setPointValue;
|
||||
float errorLimit;
|
||||
} floatingLimit;
|
||||
/*
|
||||
** EVENT_OUT_OF_RANGE
|
||||
*/
|
||||
struct {
|
||||
float exceedingValue;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
float deadband;
|
||||
float exceededLimit;
|
||||
} outOfRange;
|
||||
/*
|
||||
** EVENT_CHANGE_OF_LIFE_SAFETY
|
||||
*/
|
||||
struct {
|
||||
BACNET_LIFE_SAFETY_STATE newState;
|
||||
BACNET_LIFE_SAFETY_MODE newMode;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
BACNET_LIFE_SAFETY_OPERATION operationExpected;
|
||||
} changeOfLifeSafety;
|
||||
/*
|
||||
** EVENT_EXTENDED
|
||||
**
|
||||
** Not Supported!
|
||||
*/
|
||||
/*
|
||||
** EVENT_BUFFER_READY
|
||||
*/
|
||||
struct {
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE bufferProperty;
|
||||
uint32_t previousNotification;
|
||||
uint32_t currentNotification;
|
||||
} bufferReady;
|
||||
/*
|
||||
** EVENT_UNSIGNED_RANGE
|
||||
*/
|
||||
struct {
|
||||
uint32_t exceedingValue;
|
||||
BACNET_BIT_STRING statusFlags;
|
||||
uint32_t exceededLimit;
|
||||
} unsignedRange;
|
||||
} notificationParams;
|
||||
} BACNET_EVENT_NOTIFICATION_DATA;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Creates a Confirmed Event Notification APDU
|
||||
**
|
||||
****************************************************/
|
||||
int cevent_notify_encode_apdu(
|
||||
uint8_t * apdu,
|
||||
uint8_t invoke_id,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data);
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Creates an Unconfirmed Event Notification APDU
|
||||
**
|
||||
****************************************************/
|
||||
int uevent_notify_encode_apdu(
|
||||
uint8_t * apdu,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data);
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Encodes the service data part of Event Notification
|
||||
**
|
||||
****************************************************/
|
||||
int event_notify_encode_service_request(
|
||||
uint8_t * apdu,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data);
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Decodes the service data part of Event Notification
|
||||
**
|
||||
****************************************************/
|
||||
int event_notify_decode_service_request(
|
||||
uint8_t * apdu,
|
||||
unsigned apdu_len,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data);
|
||||
|
||||
/***************************************************
|
||||
**
|
||||
** Sends an Unconfirmed Event Notifcation to a dest
|
||||
**
|
||||
****************************************************/
|
||||
int uevent_notify_send(
|
||||
uint8_t * buffer,
|
||||
BACNET_EVENT_NOTIFICATION_DATA * data,
|
||||
BACNET_ADDRESS * dest);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* BACNET_EVENT_H_ */
|
||||
|
||||
@@ -47,12 +47,12 @@ extern "C" {
|
||||
|
||||
/* copy len bytes from src to offset of dest if there is enough space. */
|
||||
/* returns 0 if there is not enough space, or the number of bytes copied. */
|
||||
size_t memcopy(
|
||||
void * dest,
|
||||
void * src,
|
||||
size_t offset, /* where in dest to put the data */
|
||||
size_t len, /* amount of data to copy */
|
||||
size_t max); /* total size of destination */
|
||||
size_t memcopy(
|
||||
void *dest,
|
||||
void *src,
|
||||
size_t offset, /* where in dest to put the data */
|
||||
size_t len, /* amount of data to copy */
|
||||
size_t max); /* total size of destination */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ extern "C" {
|
||||
uint8_t * apdu,
|
||||
size_t max_apdu,
|
||||
uint8_t invoke_id,
|
||||
BACNET_READ_ACCESS_DATA *read_access_data);
|
||||
BACNET_READ_ACCESS_DATA * read_access_data);
|
||||
|
||||
/* decode the object portion of the service request only */
|
||||
int rpm_decode_object_id(
|
||||
|
||||
@@ -1,78 +1,76 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#ifndef _TIMESTAMP_H_
|
||||
#define _TIMESTAMP_H_
|
||||
|
||||
#include "bacdcode.h"
|
||||
|
||||
typedef enum {
|
||||
TIME_STAMP_TIME = 0,
|
||||
TIME_STAMP_SEQUENCE = 1,
|
||||
TIME_STAMP_DATETIME = 2,
|
||||
} BACNET_TIMESTAMP_TAG;
|
||||
|
||||
typedef uint8_t TYPE_BACNET_TIMESTAMP_TYPE;
|
||||
|
||||
typedef struct {
|
||||
TYPE_BACNET_TIMESTAMP_TYPE tag;
|
||||
union {
|
||||
BACNET_TIME time;
|
||||
uint16_t sequenceNum;
|
||||
BACNET_DATE_TIME dateTime;
|
||||
} value;
|
||||
} BACNET_TIMESTAMP;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
|
||||
int bacapp_encode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value);
|
||||
|
||||
int bacapp_decode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#ifndef _TIMESTAMP_H_
|
||||
#define _TIMESTAMP_H_
|
||||
|
||||
#include "bacdcode.h"
|
||||
|
||||
typedef enum {
|
||||
TIME_STAMP_TIME = 0,
|
||||
TIME_STAMP_SEQUENCE = 1,
|
||||
TIME_STAMP_DATETIME = 2,
|
||||
} BACNET_TIMESTAMP_TAG;
|
||||
|
||||
typedef uint8_t TYPE_BACNET_TIMESTAMP_TYPE;
|
||||
|
||||
typedef struct {
|
||||
TYPE_BACNET_TIMESTAMP_TYPE tag;
|
||||
union {
|
||||
BACNET_TIME time;
|
||||
uint16_t sequenceNum;
|
||||
BACNET_DATE_TIME dateTime;
|
||||
} value;
|
||||
} BACNET_TIMESTAMP;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
|
||||
int bacapp_encode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value);
|
||||
|
||||
int bacapp_decode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
|
||||
+19
-18
@@ -1,18 +1,19 @@
|
||||
#ifndef __MAIN_H__
|
||||
#define __MAIN_H__
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* To use this exported function of dll, include this header
|
||||
* in your project.
|
||||
*/
|
||||
|
||||
#ifdef BUILD_DLL
|
||||
#define DLL_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DLL_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
void DLL_EXPORT SomeFunction(const LPCSTR sometext);
|
||||
|
||||
#endif // __MAIN_H__
|
||||
#ifndef __MAIN_H__
|
||||
#define __MAIN_H__
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* To use this exported function of dll, include this header
|
||||
* in your project.
|
||||
*/
|
||||
|
||||
#ifdef BUILD_DLL
|
||||
#define DLL_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DLL_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
void DLL_EXPORT SomeFunction(
|
||||
const LPCSTR sometext);
|
||||
|
||||
#endif // __MAIN_H__
|
||||
|
||||
+159
-159
@@ -1,159 +1,159 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/* Analog Input Objects customize for your use */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacenum.h"
|
||||
#include "config.h"
|
||||
|
||||
/* Analog Input = Photocell */
|
||||
#define MAX_ANALOG_INPUTS 9
|
||||
#if (MAX_ANALOG_INPUTS > 9)
|
||||
#error Modify the Analog_Input_Name to handle multiple digits
|
||||
#endif
|
||||
|
||||
float Present_Value[MAX_ANALOG_INPUTS];
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Input_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_INPUTS)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Analog_Input_Count(
|
||||
void)
|
||||
{
|
||||
return MAX_ANALOG_INPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
uint32_t Analog_Input_Index_To_Instance(
|
||||
unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Analog_Input_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
return object_instance;
|
||||
}
|
||||
|
||||
|
||||
char *Analog_Input_Name(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
static char text_string[5] = "AI-0"; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_ANALOG_INPUTS) {
|
||||
text_string[3] = '0' + (uint8_t) 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 apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned object_index;
|
||||
|
||||
|
||||
(void) array_index;
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
|
||||
object_instance);
|
||||
break;
|
||||
/* note: Name and Description don't have to be the same.
|
||||
You could make Description writable and different.
|
||||
Note that Object-Name must be unique in this device */
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Analog_Input_Name(object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_INPUT);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
object_index = Analog_Input_Instance_To_Index(object_instance);
|
||||
apdu_len =
|
||||
encode_application_real(&apdu[0], Present_Value[object_index]);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_EVENT_STATE:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||
break;
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
apdu_len = encode_application_boolean(&apdu[0], false);
|
||||
break;
|
||||
case PROP_UNITS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/* Analog Input Objects customize for your use */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacenum.h"
|
||||
#include "config.h"
|
||||
|
||||
/* Analog Input = Photocell */
|
||||
#define MAX_ANALOG_INPUTS 9
|
||||
#if (MAX_ANALOG_INPUTS > 9)
|
||||
#error Modify the Analog_Input_Name to handle multiple digits
|
||||
#endif
|
||||
|
||||
float Present_Value[MAX_ANALOG_INPUTS];
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Input_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_INPUTS)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Analog_Input_Count(
|
||||
void)
|
||||
{
|
||||
return MAX_ANALOG_INPUTS;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
uint32_t Analog_Input_Index_To_Instance(
|
||||
unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. */
|
||||
unsigned Analog_Input_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
return object_instance;
|
||||
}
|
||||
|
||||
|
||||
char *Analog_Input_Name(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
static char text_string[5] = "AI-0"; /* okay for single thread */
|
||||
|
||||
if (object_instance < MAX_ANALOG_INPUTS) {
|
||||
text_string[3] = '0' + (uint8_t) 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 apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned object_index;
|
||||
|
||||
|
||||
(void) array_index;
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
|
||||
object_instance);
|
||||
break;
|
||||
/* note: Name and Description don't have to be the same.
|
||||
You could make Description writable and different.
|
||||
Note that Object-Name must be unique in this device */
|
||||
case PROP_OBJECT_NAME:
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Analog_Input_Name(object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_INPUT);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
object_index = Analog_Input_Instance_To_Index(object_instance);
|
||||
apdu_len =
|
||||
encode_application_real(&apdu[0], Present_Value[object_index]);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_EVENT_STATE:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||
break;
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
apdu_len = encode_application_boolean(&apdu[0], false);
|
||||
break;
|
||||
case PROP_UNITS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
+123
-123
@@ -1,123 +1,123 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2007 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "bits.h"
|
||||
#include "apdu.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacenum.h"
|
||||
#include "handlers.h"
|
||||
|
||||
bool apdu_service_supported(
|
||||
BACNET_SERVICES_SUPPORTED service_supported)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (service_supported == SERVICE_SUPPORTED_READ_PROPERTY) {
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint16_t apdu_decode_confirmed_service_request(
|
||||
uint8_t * apdu, /* APDU data */
|
||||
uint16_t apdu_len,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data,
|
||||
uint8_t * service_choice,
|
||||
uint8_t ** service_request,
|
||||
uint16_t * service_request_len)
|
||||
{
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
service_data->segmented_message = (apdu[0] & BIT3) ? true : false;
|
||||
service_data->more_follows = (apdu[0] & BIT2) ? true : false;
|
||||
service_data->segmented_response_accepted =
|
||||
(apdu[0] & BIT1) ? true : false;
|
||||
service_data->max_segs = decode_max_segs(apdu[1]);
|
||||
service_data->max_resp = decode_max_apdu(apdu[1]);
|
||||
service_data->invoke_id = apdu[2];
|
||||
len = 3;
|
||||
if (service_data->segmented_message) {
|
||||
service_data->sequence_number = apdu[len++];
|
||||
service_data->proposed_window_number = apdu[len++];
|
||||
}
|
||||
*service_choice = apdu[len++];
|
||||
*service_request = &apdu[len];
|
||||
*service_request_len = apdu_len - len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void apdu_handler(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t * apdu, /* APDU data */
|
||||
uint16_t apdu_len)
|
||||
{
|
||||
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
|
||||
uint8_t service_choice = 0;
|
||||
uint8_t *service_request = NULL;
|
||||
uint16_t service_request_len = 0;
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
if (apdu) {
|
||||
/* PDU Type */
|
||||
switch (apdu[0] & 0xF0) {
|
||||
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
|
||||
len = apdu_decode_confirmed_service_request(&apdu[0], /* APDU data */
|
||||
apdu_len, &service_data, &service_choice, &service_request,
|
||||
&service_request_len);
|
||||
if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
|
||||
handler_read_property(service_request, service_request_len,
|
||||
src, &service_data);
|
||||
} else {
|
||||
handler_unrecognized_service(service_request,
|
||||
service_request_len, src, &service_data);
|
||||
}
|
||||
break;
|
||||
case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
|
||||
case PDU_TYPE_SIMPLE_ACK:
|
||||
case PDU_TYPE_COMPLEX_ACK:
|
||||
case PDU_TYPE_SEGMENT_ACK:
|
||||
case PDU_TYPE_ERROR:
|
||||
case PDU_TYPE_REJECT:
|
||||
case PDU_TYPE_ABORT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2007 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "bits.h"
|
||||
#include "apdu.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacenum.h"
|
||||
#include "handlers.h"
|
||||
|
||||
bool apdu_service_supported(
|
||||
BACNET_SERVICES_SUPPORTED service_supported)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (service_supported == SERVICE_SUPPORTED_READ_PROPERTY) {
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint16_t apdu_decode_confirmed_service_request(
|
||||
uint8_t * apdu, /* APDU data */
|
||||
uint16_t apdu_len,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data,
|
||||
uint8_t * service_choice,
|
||||
uint8_t ** service_request,
|
||||
uint16_t * service_request_len)
|
||||
{
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
service_data->segmented_message = (apdu[0] & BIT3) ? true : false;
|
||||
service_data->more_follows = (apdu[0] & BIT2) ? true : false;
|
||||
service_data->segmented_response_accepted =
|
||||
(apdu[0] & BIT1) ? true : false;
|
||||
service_data->max_segs = decode_max_segs(apdu[1]);
|
||||
service_data->max_resp = decode_max_apdu(apdu[1]);
|
||||
service_data->invoke_id = apdu[2];
|
||||
len = 3;
|
||||
if (service_data->segmented_message) {
|
||||
service_data->sequence_number = apdu[len++];
|
||||
service_data->proposed_window_number = apdu[len++];
|
||||
}
|
||||
*service_choice = apdu[len++];
|
||||
*service_request = &apdu[len];
|
||||
*service_request_len = apdu_len - len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void apdu_handler(
|
||||
BACNET_ADDRESS * src,
|
||||
uint8_t * apdu, /* APDU data */
|
||||
uint16_t apdu_len)
|
||||
{
|
||||
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
|
||||
uint8_t service_choice = 0;
|
||||
uint8_t *service_request = NULL;
|
||||
uint16_t service_request_len = 0;
|
||||
uint16_t len = 0; /* counts where we are in PDU */
|
||||
|
||||
if (apdu) {
|
||||
/* PDU Type */
|
||||
switch (apdu[0] & 0xF0) {
|
||||
case PDU_TYPE_CONFIRMED_SERVICE_REQUEST:
|
||||
len = apdu_decode_confirmed_service_request(&apdu[0], /* APDU data */
|
||||
apdu_len, &service_data, &service_choice, &service_request,
|
||||
&service_request_len);
|
||||
if (service_choice == SERVICE_CONFIRMED_READ_PROPERTY) {
|
||||
handler_read_property(service_request, service_request_len,
|
||||
src, &service_data);
|
||||
} else {
|
||||
handler_unrecognized_service(service_request,
|
||||
service_request_len, src, &service_data);
|
||||
}
|
||||
break;
|
||||
case PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST:
|
||||
case PDU_TYPE_SIMPLE_ACK:
|
||||
case PDU_TYPE_COMPLEX_ACK:
|
||||
case PDU_TYPE_SEGMENT_ACK:
|
||||
case PDU_TYPE_ERROR:
|
||||
case PDU_TYPE_REJECT:
|
||||
case PDU_TYPE_ABORT:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
+253
-253
@@ -1,253 +1,253 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/* Analog Value Objects - customize for your use */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "hardware.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacenum.h"
|
||||
#include "bacapp.h"
|
||||
#include "config.h" /* the custom stuff */
|
||||
#include "wp.h"
|
||||
#include "av.h"
|
||||
|
||||
#if (MAX_ANALOG_VALUES > 10)
|
||||
#error Modify the Analog_Value_Name to handle multiple digits
|
||||
#endif
|
||||
|
||||
float AV_Present_Value[MAX_ANALOG_VALUES];
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Value_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_VALUES)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then count how many you have */
|
||||
unsigned Analog_Value_Count(
|
||||
void)
|
||||
{
|
||||
return MAX_ANALOG_VALUES;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the instance */
|
||||
/* that correlates to the correct index */
|
||||
uint32_t Analog_Value_Index_To_Instance(
|
||||
unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the index */
|
||||
/* that correlates to the correct instance number */
|
||||
unsigned Analog_Value_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
return object_instance;
|
||||
}
|
||||
|
||||
/* note: the object name must be unique within this device */
|
||||
char *Analog_Value_Name(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
static char text_string[5] = "AV-"; /* okay for single thread */
|
||||
|
||||
text_string[3] = '0' + (uint8_t) object_instance;
|
||||
|
||||
return text_string;
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Analog_Value_Encode_Property_APDU(
|
||||
uint8_t * apdu,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID property,
|
||||
int32_t array_index,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned object_index;
|
||||
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
|
||||
object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Analog_Value_Name(object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
object_index = Analog_Value_Instance_To_Index(object_instance);
|
||||
apdu_len =
|
||||
encode_application_real(&apdu[0],
|
||||
AV_Present_Value[object_index]);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_EVENT_STATE:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||
break;
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
apdu_len = encode_application_boolean(&apdu[0], false);
|
||||
break;
|
||||
case PROP_UNITS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Analog_Value_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
|
||||
if (!Analog_Value_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 */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
/* FIXME: len < application_data_len: more data? */
|
||||
/* FIXME: len == 0: unable to decode? */
|
||||
switch (wp_data->object_property) {
|
||||
case PROP_PRESENT_VALUE:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
|
||||
object_index =
|
||||
Analog_Value_Instance_To_Index(wp_data->object_instance);
|
||||
AV_Present_Value[object_index] = value.type.Real;
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
void testAnalog_Value(
|
||||
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_VALUE;
|
||||
uint32_t decoded_instance = 0;
|
||||
uint32_t instance = 123;
|
||||
BACNET_ERROR_CLASS error_class;
|
||||
BACNET_ERROR_CODE error_code;
|
||||
|
||||
len =
|
||||
Analog_Value_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_VALUE);
|
||||
ct_test(pTest, decoded_instance == instance);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TEST_ANALOG_VALUE
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Analog Value", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testAnalog_Value);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* TEST_ANALOG_VALUE */
|
||||
#endif /* TEST */
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/* Analog Value Objects - customize for your use */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "hardware.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacenum.h"
|
||||
#include "bacapp.h"
|
||||
#include "config.h" /* the custom stuff */
|
||||
#include "wp.h"
|
||||
#include "av.h"
|
||||
|
||||
#if (MAX_ANALOG_VALUES > 10)
|
||||
#error Modify the Analog_Value_Name to handle multiple digits
|
||||
#endif
|
||||
|
||||
float AV_Present_Value[MAX_ANALOG_VALUES];
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need validate that the */
|
||||
/* given instance exists */
|
||||
bool Analog_Value_Valid_Instance(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
if (object_instance < MAX_ANALOG_VALUES)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then count how many you have */
|
||||
unsigned Analog_Value_Count(
|
||||
void)
|
||||
{
|
||||
return MAX_ANALOG_VALUES;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the instance */
|
||||
/* that correlates to the correct index */
|
||||
uint32_t Analog_Value_Index_To_Instance(
|
||||
unsigned index)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
/* we simply have 0-n object instances. Yours might be */
|
||||
/* more complex, and then you need to return the index */
|
||||
/* that correlates to the correct instance number */
|
||||
unsigned Analog_Value_Instance_To_Index(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
return object_instance;
|
||||
}
|
||||
|
||||
/* note: the object name must be unique within this device */
|
||||
char *Analog_Value_Name(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
static char text_string[5] = "AV-"; /* okay for single thread */
|
||||
|
||||
text_string[3] = '0' + (uint8_t) object_instance;
|
||||
|
||||
return text_string;
|
||||
}
|
||||
|
||||
/* return apdu len, or -1 on error */
|
||||
int Analog_Value_Encode_Property_APDU(
|
||||
uint8_t * apdu,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_ID property,
|
||||
int32_t array_index,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned object_index;
|
||||
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
|
||||
object_instance);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Analog_Value_Name(object_instance));
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
object_index = Analog_Value_Instance_To_Index(object_instance);
|
||||
apdu_len =
|
||||
encode_application_real(&apdu[0],
|
||||
AV_Present_Value[object_index]);
|
||||
break;
|
||||
case PROP_STATUS_FLAGS:
|
||||
bitstring_init(&bit_string);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_EVENT_STATE:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
|
||||
break;
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
apdu_len = encode_application_boolean(&apdu[0], false);
|
||||
break;
|
||||
case PROP_UNITS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/* returns true if successful */
|
||||
bool Analog_Value_Write_Property(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
unsigned int object_index = 0;
|
||||
int len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE value;
|
||||
|
||||
if (!Analog_Value_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 */
|
||||
len =
|
||||
bacapp_decode_application_data(wp_data->application_data,
|
||||
wp_data->application_data_len, &value);
|
||||
/* FIXME: len < application_data_len: more data? */
|
||||
/* FIXME: len == 0: unable to decode? */
|
||||
switch (wp_data->object_property) {
|
||||
case PROP_PRESENT_VALUE:
|
||||
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
|
||||
object_index =
|
||||
Analog_Value_Instance_To_Index(wp_data->object_instance);
|
||||
AV_Present_Value[object_index] = value.type.Real;
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
void testAnalog_Value(
|
||||
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_VALUE;
|
||||
uint32_t decoded_instance = 0;
|
||||
uint32_t instance = 123;
|
||||
BACNET_ERROR_CLASS error_class;
|
||||
BACNET_ERROR_CODE error_code;
|
||||
|
||||
len =
|
||||
Analog_Value_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_VALUE);
|
||||
ct_test(pTest, decoded_instance == instance);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TEST_ANALOG_VALUE
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Analog Value", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testAnalog_Value);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* TEST_ANALOG_VALUE */
|
||||
#endif /* TEST */
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#ifndef AVR035_H
|
||||
#define AVR035_H
|
||||
|
||||
/* from AVR035: Efficient C Coding for AVR */
|
||||
|
||||
/* a=register, b=bit number to act upon */
|
||||
#define BIT_SET(a,b) ((a) |= (1<<(b)))
|
||||
#define BIT_CLEAR(a,b) ((a) &= ~(1<<(b)))
|
||||
#define BIT_FLIP(a,b) ((a) ^= (1<<(b)))
|
||||
#define BIT_CHECK(a,b) ((a) & (1<<(b)))
|
||||
|
||||
/* x=target variable, y=mask */
|
||||
#define BITMASK_SET(x,y) ((x) |= (y))
|
||||
#define BITMASK_CLEAR(x,y) ((x) &= (~(y)))
|
||||
#define BITMASK_FLIP(x,y) ((x) ^= (y))
|
||||
#define BITMASK_CHECK(x,y) ((x) & (y))
|
||||
|
||||
#endif
|
||||
#ifndef AVR035_H
|
||||
#define AVR035_H
|
||||
|
||||
/* from AVR035: Efficient C Coding for AVR */
|
||||
|
||||
/* a=register, b=bit number to act upon */
|
||||
#define BIT_SET(a,b) ((a) |= (1<<(b)))
|
||||
#define BIT_CLEAR(a,b) ((a) &= ~(1<<(b)))
|
||||
#define BIT_FLIP(a,b) ((a) ^= (1<<(b)))
|
||||
#define BIT_CHECK(a,b) ((a) & (1<<(b)))
|
||||
|
||||
/* x=target variable, y=mask */
|
||||
#define BITMASK_SET(x,y) ((x) |= (y))
|
||||
#define BITMASK_CLEAR(x,y) ((x) &= (~(y)))
|
||||
#define BITMASK_FLIP(x,y) ((x) ^= (y))
|
||||
#define BITMASK_CHECK(x,y) ((x) & (y))
|
||||
|
||||
#endif
|
||||
|
||||
+330
-331
@@ -1,331 +1,330 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacstr.h"
|
||||
#include "bacenum.h"
|
||||
#include "apdu.h"
|
||||
#include "dcc.h"
|
||||
#include "dlmstp.h"
|
||||
#include "rs485.h"
|
||||
#include "version.h"
|
||||
/* objects */
|
||||
#include "device.h"
|
||||
#include "av.h"
|
||||
|
||||
/* note: you really only need to define variables for
|
||||
properties that are writable or that may change.
|
||||
The properties that are constant can be hard coded
|
||||
into the read-property encoding. */
|
||||
static uint32_t Object_Instance_Number = 260001;
|
||||
static char *Object_Name = "My Device";
|
||||
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
|
||||
|
||||
void Device_Init(
|
||||
void)
|
||||
{
|
||||
/* Reinitialize_State = REINITIALIZED_STATE_IDLE; */
|
||||
/* dcc_set_status_duration(COMMUNICATION_ENABLE, 0); */
|
||||
/* FIXME: Get the data from the eeprom */
|
||||
/* I2C_Read_Block(EEPROM_DEVICE_ADDRESS,
|
||||
(char *)&Object_Instance_Number,
|
||||
sizeof(Object_Instance_Number),
|
||||
EEPROM_BACNET_ID_ADDR); */
|
||||
}
|
||||
|
||||
/* methods to manipulate the data */
|
||||
uint32_t Device_Object_Instance_Number(
|
||||
void)
|
||||
{
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
|
||||
if (object_id <= BACNET_MAX_INSTANCE) {
|
||||
Object_Instance_Number = object_id;
|
||||
/* FIXME: Write the data to the eeprom */
|
||||
/* I2C_Write_Block(
|
||||
EEPROM_DEVICE_ADDRESS,
|
||||
(char *)&Object_Instance_Number,
|
||||
sizeof(Object_Instance_Number),
|
||||
EEPROM_BACNET_ID_ADDR); */
|
||||
} else
|
||||
status = false;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
{
|
||||
/* BACnet allows for a wildcard instance number */
|
||||
return ((Object_Instance_Number == object_id) ||
|
||||
(object_id == BACNET_MAX_INSTANCE));
|
||||
}
|
||||
|
||||
uint16_t Device_Vendor_Identifier(
|
||||
void)
|
||||
{
|
||||
return BACNET_VENDOR_ID;
|
||||
}
|
||||
|
||||
unsigned Device_Object_List_Count(
|
||||
void)
|
||||
{
|
||||
unsigned count = 1; /* at least 1 for device object */
|
||||
|
||||
#if MAX_ANALOG_VALUES
|
||||
/* FIXME: add objects as needed */
|
||||
count += Analog_Value_Count();
|
||||
#endif
|
||||
#if MAX_BINARY_VALUES
|
||||
/* FIXME: add objects as needed */
|
||||
count += Binary_Value_Count();
|
||||
#endif
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool Device_Object_List_Identifier(
|
||||
unsigned array_index,
|
||||
int *object_type,
|
||||
uint32_t * instance)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned object_index = 0;
|
||||
unsigned object_count = 0;
|
||||
|
||||
/* device object */
|
||||
if (array_index == 1) {
|
||||
*object_type = OBJECT_DEVICE;
|
||||
*instance = Object_Instance_Number;
|
||||
status = true;
|
||||
}
|
||||
/* normalize the index since
|
||||
we know it is not the previous objects */
|
||||
/* array index starts at 1 */
|
||||
object_index = array_index - 1;
|
||||
/* 1 for the device object */
|
||||
object_count = 1;
|
||||
/* FIXME: add objects as needed */
|
||||
#if MAX_ANALOG_VALUES
|
||||
/* analog value objects */
|
||||
if (!status) {
|
||||
/* array index starts at 1, and 1 for the device object */
|
||||
object_index -= object_count;
|
||||
object_count = Analog_Value_Count();
|
||||
if (object_index < object_count) {
|
||||
*object_type = OBJECT_ANALOG_VALUE;
|
||||
*instance = Analog_Value_Index_To_Instance(object_index);
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if MAX_BINARY_VALUES
|
||||
/* binary value objects */
|
||||
if (!status) {
|
||||
object_index -= object_count;
|
||||
object_count = Binary_Value_Count();
|
||||
/* is it a valid index for this object? */
|
||||
if (object_index < object_count) {
|
||||
*object_type = OBJECT_BINARY_VALUE;
|
||||
*instance = Binary_Value_Index_To_Instance(object_index);
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* return the length of the apdu encoded or -1 for error */
|
||||
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 apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned i = 0;
|
||||
int object_type = 0;
|
||||
uint32_t instance = 0;
|
||||
unsigned count = 0;
|
||||
|
||||
/* FIXME: change the hardcoded names to suit your application */
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
Object_Instance_Number);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
characterstring_init_ansi(&char_string, Object_Name);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
|
||||
break;
|
||||
case PROP_SYSTEM_STATUS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], System_Status);
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
characterstring_init_ansi(&char_string, BACNET_VENDOR_NAME);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Vendor_Identifier());
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
characterstring_init_ansi(&char_string, "GNU Demo");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_FIRMWARE_REVISION:
|
||||
characterstring_init_ansi(&char_string, BACNET_VERSION_TEXT);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_APPLICATION_SOFTWARE_VERSION:
|
||||
characterstring_init_ansi(&char_string, "1.0");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 1);
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 5);
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED) i));
|
||||
}
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
|
||||
/* Note: this is the list of objects that can be in this device,
|
||||
not a list of objects that this device can access */
|
||||
bitstring_init(&bit_string);
|
||||
/* must have the bit string as big as it can be */
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
}
|
||||
/* FIXME: indicate the objects that YOU support */
|
||||
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
|
||||
#if MAX_ANALOG_VALUES
|
||||
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
|
||||
#endif
|
||||
#if MAX_BINARY_VALUES
|
||||
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
|
||||
#endif
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_OBJECT_LIST:
|
||||
count = Device_Object_List_Count();
|
||||
/* Array element zero is the number of objects in the list */
|
||||
if (array_index == 0)
|
||||
apdu_len = encode_application_unsigned(&apdu[0], count);
|
||||
/* if no index was specified, then try to encode the entire list */
|
||||
/* into one packet. Note that more than likely you will have */
|
||||
/* to return an error if the number of encoded objects exceeds */
|
||||
/* your maximum APDU size. */
|
||||
else if (array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
Device_Object_List_Identifier(i, &object_type, &instance);
|
||||
len =
|
||||
encode_application_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? */
|
||||
if ((apdu_len + len) >= MAX_APDU) {
|
||||
*error_class = ERROR_CLASS_SERVICES;
|
||||
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(array_index, &object_type,
|
||||
&instance))
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
apdu_len = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROP_MAX_APDU_LENGTH_ACCEPTED:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], SEGMENTATION_NONE);
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 60000);
|
||||
break;
|
||||
case PROP_NUMBER_OF_APDU_RETRIES:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
case PROP_DEVICE_ADDRESS_BINDING:
|
||||
/* FIXME: encode the list here, if it exists */
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacstr.h"
|
||||
#include "bacenum.h"
|
||||
#include "apdu.h"
|
||||
#include "dcc.h"
|
||||
#include "dlmstp.h"
|
||||
#include "rs485.h"
|
||||
#include "version.h"
|
||||
/* objects */
|
||||
#include "device.h"
|
||||
#include "av.h"
|
||||
|
||||
/* note: you really only need to define variables for
|
||||
properties that are writable or that may change.
|
||||
The properties that are constant can be hard coded
|
||||
into the read-property encoding. */
|
||||
static uint32_t Object_Instance_Number = 260001;
|
||||
static char *Object_Name = "My Device";
|
||||
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
|
||||
|
||||
void Device_Init(
|
||||
void)
|
||||
{
|
||||
/* Reinitialize_State = REINITIALIZED_STATE_IDLE; */
|
||||
/* dcc_set_status_duration(COMMUNICATION_ENABLE, 0); */
|
||||
/* FIXME: Get the data from the eeprom */
|
||||
/* I2C_Read_Block(EEPROM_DEVICE_ADDRESS,
|
||||
(char *)&Object_Instance_Number,
|
||||
sizeof(Object_Instance_Number),
|
||||
EEPROM_BACNET_ID_ADDR); */
|
||||
}
|
||||
|
||||
/* methods to manipulate the data */
|
||||
uint32_t Device_Object_Instance_Number(
|
||||
void)
|
||||
{
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
|
||||
if (object_id <= BACNET_MAX_INSTANCE) {
|
||||
Object_Instance_Number = object_id;
|
||||
/* FIXME: Write the data to the eeprom */
|
||||
/* I2C_Write_Block(
|
||||
EEPROM_DEVICE_ADDRESS,
|
||||
(char *)&Object_Instance_Number,
|
||||
sizeof(Object_Instance_Number),
|
||||
EEPROM_BACNET_ID_ADDR); */
|
||||
} else
|
||||
status = false;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
{
|
||||
/* BACnet allows for a wildcard instance number */
|
||||
return ((Object_Instance_Number == object_id) ||
|
||||
(object_id == BACNET_MAX_INSTANCE));
|
||||
}
|
||||
|
||||
uint16_t Device_Vendor_Identifier(
|
||||
void)
|
||||
{
|
||||
return BACNET_VENDOR_ID;
|
||||
}
|
||||
|
||||
unsigned Device_Object_List_Count(
|
||||
void)
|
||||
{
|
||||
unsigned count = 1; /* at least 1 for device object */
|
||||
|
||||
#if MAX_ANALOG_VALUES
|
||||
/* FIXME: add objects as needed */
|
||||
count += Analog_Value_Count();
|
||||
#endif
|
||||
#if MAX_BINARY_VALUES
|
||||
/* FIXME: add objects as needed */
|
||||
count += Binary_Value_Count();
|
||||
#endif
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool Device_Object_List_Identifier(
|
||||
unsigned array_index,
|
||||
int *object_type,
|
||||
uint32_t * instance)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned object_index = 0;
|
||||
unsigned object_count = 0;
|
||||
|
||||
/* device object */
|
||||
if (array_index == 1) {
|
||||
*object_type = OBJECT_DEVICE;
|
||||
*instance = Object_Instance_Number;
|
||||
status = true;
|
||||
}
|
||||
/* normalize the index since
|
||||
we know it is not the previous objects */
|
||||
/* array index starts at 1 */
|
||||
object_index = array_index - 1;
|
||||
/* 1 for the device object */
|
||||
object_count = 1;
|
||||
/* FIXME: add objects as needed */
|
||||
#if MAX_ANALOG_VALUES
|
||||
/* analog value objects */
|
||||
if (!status) {
|
||||
/* array index starts at 1, and 1 for the device object */
|
||||
object_index -= object_count;
|
||||
object_count = Analog_Value_Count();
|
||||
if (object_index < object_count) {
|
||||
*object_type = OBJECT_ANALOG_VALUE;
|
||||
*instance = Analog_Value_Index_To_Instance(object_index);
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if MAX_BINARY_VALUES
|
||||
/* binary value objects */
|
||||
if (!status) {
|
||||
object_index -= object_count;
|
||||
object_count = Binary_Value_Count();
|
||||
/* is it a valid index for this object? */
|
||||
if (object_index < object_count) {
|
||||
*object_type = OBJECT_BINARY_VALUE;
|
||||
*instance = Binary_Value_Index_To_Instance(object_index);
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* return the length of the apdu encoded or -1 for error */
|
||||
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 apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned i = 0;
|
||||
int object_type = 0;
|
||||
uint32_t instance = 0;
|
||||
unsigned count = 0;
|
||||
|
||||
/* FIXME: change the hardcoded names to suit your application */
|
||||
switch (property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
Object_Instance_Number);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
characterstring_init_ansi(&char_string, Object_Name);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
|
||||
break;
|
||||
case PROP_SYSTEM_STATUS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], System_Status);
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
characterstring_init_ansi(&char_string, BACNET_VENDOR_NAME);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Vendor_Identifier());
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
characterstring_init_ansi(&char_string, "GNU Demo");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_FIRMWARE_REVISION:
|
||||
characterstring_init_ansi(&char_string, BACNET_VERSION_TEXT);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_APPLICATION_SOFTWARE_VERSION:
|
||||
characterstring_init_ansi(&char_string, "1.0");
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 1);
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 5);
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED) i));
|
||||
}
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
|
||||
/* Note: this is the list of objects that can be in this device,
|
||||
not a list of objects that this device can access */
|
||||
bitstring_init(&bit_string);
|
||||
/* must have the bit string as big as it can be */
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
}
|
||||
/* FIXME: indicate the objects that YOU support */
|
||||
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
|
||||
#if MAX_ANALOG_VALUES
|
||||
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
|
||||
#endif
|
||||
#if MAX_BINARY_VALUES
|
||||
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
|
||||
#endif
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_OBJECT_LIST:
|
||||
count = Device_Object_List_Count();
|
||||
/* Array element zero is the number of objects in the list */
|
||||
if (array_index == 0)
|
||||
apdu_len = encode_application_unsigned(&apdu[0], count);
|
||||
/* if no index was specified, then try to encode the entire list */
|
||||
/* into one packet. Note that more than likely you will have */
|
||||
/* to return an error if the number of encoded objects exceeds */
|
||||
/* your maximum APDU size. */
|
||||
else if (array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
Device_Object_List_Identifier(i, &object_type, &instance);
|
||||
len =
|
||||
encode_application_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? */
|
||||
if ((apdu_len + len) >= MAX_APDU) {
|
||||
*error_class = ERROR_CLASS_SERVICES;
|
||||
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (Device_Object_List_Identifier(array_index, &object_type,
|
||||
&instance))
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
apdu_len = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROP_MAX_APDU_LENGTH_ACCEPTED:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0], SEGMENTATION_NONE);
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 60000);
|
||||
break;
|
||||
case PROP_NUMBER_OF_APDU_RETRIES:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
case PROP_DEVICE_ADDRESS_BINDING:
|
||||
/* FIXME: encode the list here, if it exists */
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], 0);
|
||||
break;
|
||||
default:
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
+770
-765
File diff suppressed because it is too large
Load Diff
+173
-173
@@ -1,173 +1,173 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacerror.h"
|
||||
#include "apdu.h"
|
||||
#include "npdu.h"
|
||||
#include "abort.h"
|
||||
#include "rp.h"
|
||||
/* demo objects */
|
||||
#include "device.h"
|
||||
#if MAX_ANALOG_VALUES
|
||||
#include "av.h"
|
||||
#endif
|
||||
#if MAX_BINARY_VALUES
|
||||
#include "bv.h"
|
||||
#endif
|
||||
|
||||
/* Encodes the property APDU and returns the length,
|
||||
or sets the error, and returns -1 */
|
||||
int Encode_Property_APDU(
|
||||
uint8_t * apdu,
|
||||
BACNET_READ_PROPERTY_DATA * rp_data,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = -1;
|
||||
|
||||
/* handle each object type */
|
||||
switch (rp_data->object_type) {
|
||||
case OBJECT_DEVICE:
|
||||
if (Device_Valid_Object_Instance_Number(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Device_Encode_Property_APDU(&apdu[0],
|
||||
rp_data->object_property, rp_data->array_index,
|
||||
error_class, error_code);
|
||||
}
|
||||
break;
|
||||
#if MAX_ANALOG_VALUES
|
||||
case OBJECT_ANALOG_VALUE:
|
||||
if (Analog_Value_Valid_Instance(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Analog_Value_Encode_Property_APDU(&apdu[0],
|
||||
rp_data->object_instance, rp_data->object_property,
|
||||
rp_data->array_index, error_class, error_code);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if MAX_BINARY_VALUES
|
||||
case OBJECT_BINARY_VALUE:
|
||||
if (Binary_Value_Valid_Instance(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Binary_Value_Encode_Property_APDU(&apdu[0],
|
||||
rp_data->object_instance, rp_data->object_property,
|
||||
rp_data->array_index, error_class, error_code);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
*error_class = ERROR_CLASS_OBJECT;
|
||||
*error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
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 ack_len = 0;
|
||||
int property_len = 0;
|
||||
int pdu_len = 0;
|
||||
BACNET_NPDU_DATA npdu_data;
|
||||
int bytes_sent = 0;
|
||||
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
|
||||
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
BACNET_ADDRESS my_address;
|
||||
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len =
|
||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
|
||||
&npdu_data);
|
||||
if (service_data->segmented_message) {
|
||||
/* we don't support segmentation - send an abort */
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
||||
true);
|
||||
goto RP_ABORT;
|
||||
}
|
||||
len = rp_decode_service_request(service_request, service_len, &data);
|
||||
if (len < 0) {
|
||||
/* bad decoding - send an abort */
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_OTHER, true);
|
||||
goto RP_ABORT;
|
||||
}
|
||||
/* most cases will be error */
|
||||
ack_len =
|
||||
rp_ack_encode_apdu_init(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
/* FIXME: add buffer len as passed into function or use smart buffer */
|
||||
property_len =
|
||||
Encode_Property_APDU(&Handler_Transmit_Buffer[pdu_len + ack_len],
|
||||
&data, &error_class, &error_code);
|
||||
if (property_len >= 0) {
|
||||
len =
|
||||
rp_ack_encode_apdu_object_property_end(&Handler_Transmit_Buffer
|
||||
[pdu_len + property_len + ack_len]);
|
||||
len += ack_len + property_len;
|
||||
} else {
|
||||
switch (property_len) {
|
||||
/* BACnet APDU too small to fit data, so proper response is Abort */
|
||||
case -2:
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||
break;
|
||||
default:
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
error_class, error_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
RP_ABORT:
|
||||
pdu_len += len;
|
||||
bytes_sent =
|
||||
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
|
||||
pdu_len);
|
||||
|
||||
return;
|
||||
}
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacerror.h"
|
||||
#include "apdu.h"
|
||||
#include "npdu.h"
|
||||
#include "abort.h"
|
||||
#include "rp.h"
|
||||
/* demo objects */
|
||||
#include "device.h"
|
||||
#if MAX_ANALOG_VALUES
|
||||
#include "av.h"
|
||||
#endif
|
||||
#if MAX_BINARY_VALUES
|
||||
#include "bv.h"
|
||||
#endif
|
||||
|
||||
/* Encodes the property APDU and returns the length,
|
||||
or sets the error, and returns -1 */
|
||||
int Encode_Property_APDU(
|
||||
uint8_t * apdu,
|
||||
BACNET_READ_PROPERTY_DATA * rp_data,
|
||||
BACNET_ERROR_CLASS * error_class,
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
int apdu_len = -1;
|
||||
|
||||
/* handle each object type */
|
||||
switch (rp_data->object_type) {
|
||||
case OBJECT_DEVICE:
|
||||
if (Device_Valid_Object_Instance_Number(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Device_Encode_Property_APDU(&apdu[0],
|
||||
rp_data->object_property, rp_data->array_index,
|
||||
error_class, error_code);
|
||||
}
|
||||
break;
|
||||
#if MAX_ANALOG_VALUES
|
||||
case OBJECT_ANALOG_VALUE:
|
||||
if (Analog_Value_Valid_Instance(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Analog_Value_Encode_Property_APDU(&apdu[0],
|
||||
rp_data->object_instance, rp_data->object_property,
|
||||
rp_data->array_index, error_class, error_code);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if MAX_BINARY_VALUES
|
||||
case OBJECT_BINARY_VALUE:
|
||||
if (Binary_Value_Valid_Instance(rp_data->object_instance)) {
|
||||
apdu_len =
|
||||
Binary_Value_Encode_Property_APDU(&apdu[0],
|
||||
rp_data->object_instance, rp_data->object_property,
|
||||
rp_data->array_index, error_class, error_code);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
*error_class = ERROR_CLASS_OBJECT;
|
||||
*error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
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 ack_len = 0;
|
||||
int property_len = 0;
|
||||
int pdu_len = 0;
|
||||
BACNET_NPDU_DATA npdu_data;
|
||||
int bytes_sent = 0;
|
||||
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
|
||||
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
BACNET_ADDRESS my_address;
|
||||
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len =
|
||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
|
||||
&npdu_data);
|
||||
if (service_data->segmented_message) {
|
||||
/* we don't support segmentation - send an abort */
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
||||
true);
|
||||
goto RP_ABORT;
|
||||
}
|
||||
len = rp_decode_service_request(service_request, service_len, &data);
|
||||
if (len < 0) {
|
||||
/* bad decoding - send an abort */
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_OTHER, true);
|
||||
goto RP_ABORT;
|
||||
}
|
||||
/* most cases will be error */
|
||||
ack_len =
|
||||
rp_ack_encode_apdu_init(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, &data);
|
||||
/* FIXME: add buffer len as passed into function or use smart buffer */
|
||||
property_len =
|
||||
Encode_Property_APDU(&Handler_Transmit_Buffer[pdu_len + ack_len],
|
||||
&data, &error_class, &error_code);
|
||||
if (property_len >= 0) {
|
||||
len =
|
||||
rp_ack_encode_apdu_object_property_end(&Handler_Transmit_Buffer
|
||||
[pdu_len + property_len + ack_len]);
|
||||
len += ack_len + property_len;
|
||||
} else {
|
||||
switch (property_len) {
|
||||
/* BACnet APDU too small to fit data, so proper response is Abort */
|
||||
case -2:
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
|
||||
break;
|
||||
default:
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
error_class, error_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
RP_ABORT:
|
||||
pdu_len += len;
|
||||
bytes_sent =
|
||||
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
|
||||
pdu_len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,71 +1,71 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "whois.h"
|
||||
#include "iam.h"
|
||||
#include "device.h"
|
||||
#include "client.h"
|
||||
#include "txbuf.h"
|
||||
|
||||
bool Send_I_Am = true;
|
||||
|
||||
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;
|
||||
int32_t target_device;
|
||||
|
||||
(void) src;
|
||||
len =
|
||||
whois_decode_service_request(service_request, service_len, &low_limit,
|
||||
&high_limit);
|
||||
if (len == 0) {
|
||||
Send_I_Am = true;
|
||||
} else if (len != -1) {
|
||||
/* is my device id within the limits? */
|
||||
target_device = Device_Object_Instance_Number();
|
||||
if (((target_device >= low_limit) && (target_device <= high_limit))
|
||||
||
|
||||
/* BACnet wildcard is the max instance number - everyone responds */
|
||||
((BACNET_MAX_INSTANCE >= (uint32_t) low_limit) &&
|
||||
(BACNET_MAX_INSTANCE <= (uint32_t) high_limit))) {
|
||||
Send_I_Am = true;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "whois.h"
|
||||
#include "iam.h"
|
||||
#include "device.h"
|
||||
#include "client.h"
|
||||
#include "txbuf.h"
|
||||
|
||||
bool Send_I_Am = true;
|
||||
|
||||
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;
|
||||
int32_t target_device;
|
||||
|
||||
(void) src;
|
||||
len =
|
||||
whois_decode_service_request(service_request, service_len, &low_limit,
|
||||
&high_limit);
|
||||
if (len == 0) {
|
||||
Send_I_Am = true;
|
||||
} else if (len != -1) {
|
||||
/* is my device id within the limits? */
|
||||
target_device = Device_Object_Instance_Number();
|
||||
if (((target_device >= low_limit) && (target_device <= high_limit))
|
||||
||
|
||||
/* BACnet wildcard is the max instance number - everyone responds */
|
||||
((BACNET_MAX_INSTANCE >= (uint32_t) low_limit) &&
|
||||
(BACNET_MAX_INSTANCE <= (uint32_t) high_limit))) {
|
||||
Send_I_Am = true;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
+139
-139
@@ -1,139 +1,139 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacerror.h"
|
||||
#include "apdu.h"
|
||||
#include "npdu.h"
|
||||
#include "abort.h"
|
||||
#include "wp.h"
|
||||
/* demo objects */
|
||||
#include "device.h"
|
||||
#include "av.h"
|
||||
#include "bv.h"
|
||||
|
||||
/* too big to reside on stack frame for PIC */
|
||||
static BACNET_WRITE_PROPERTY_DATA wp_data;
|
||||
|
||||
void handler_write_property(
|
||||
uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
{
|
||||
int len = 0;
|
||||
int pdu_len = 0;
|
||||
BACNET_NPDU_DATA npdu_data;
|
||||
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
|
||||
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
int bytes_sent = 0;
|
||||
BACNET_ADDRESS my_address;
|
||||
|
||||
/* decode the service request only */
|
||||
len = wp_decode_service_request(service_request, service_len, &wp_data);
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len =
|
||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
|
||||
&npdu_data);
|
||||
/* bad decoding or something we didn't understand - send an abort */
|
||||
if (len <= 0) {
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_OTHER, true);
|
||||
} else if (service_data->segmented_message) {
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
||||
true);
|
||||
} else {
|
||||
switch (wp_data.object_type) {
|
||||
case OBJECT_DEVICE:
|
||||
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
} else {
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_ANALOG_VALUE:
|
||||
if (Analog_Value_Write_Property(&wp_data, &error_class,
|
||||
&error_code)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
} else {
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_BINARY_VALUE:
|
||||
if (Binary_Value_Write_Property(&wp_data, &error_class,
|
||||
&error_code)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
} else {
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
error_class, error_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
pdu_len += len;
|
||||
bytes_sent =
|
||||
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
|
||||
pdu_len);
|
||||
|
||||
return;
|
||||
}
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "config.h"
|
||||
#include "txbuf.h"
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacerror.h"
|
||||
#include "apdu.h"
|
||||
#include "npdu.h"
|
||||
#include "abort.h"
|
||||
#include "wp.h"
|
||||
/* demo objects */
|
||||
#include "device.h"
|
||||
#include "av.h"
|
||||
#include "bv.h"
|
||||
|
||||
/* too big to reside on stack frame for PIC */
|
||||
static BACNET_WRITE_PROPERTY_DATA wp_data;
|
||||
|
||||
void handler_write_property(
|
||||
uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data)
|
||||
{
|
||||
int len = 0;
|
||||
int pdu_len = 0;
|
||||
BACNET_NPDU_DATA npdu_data;
|
||||
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
|
||||
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
int bytes_sent = 0;
|
||||
BACNET_ADDRESS my_address;
|
||||
|
||||
/* decode the service request only */
|
||||
len = wp_decode_service_request(service_request, service_len, &wp_data);
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
pdu_len =
|
||||
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
|
||||
&npdu_data);
|
||||
/* bad decoding or something we didn't understand - send an abort */
|
||||
if (len <= 0) {
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_OTHER, true);
|
||||
} else if (service_data->segmented_message) {
|
||||
len =
|
||||
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
|
||||
true);
|
||||
} else {
|
||||
switch (wp_data.object_type) {
|
||||
case OBJECT_DEVICE:
|
||||
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
} else {
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_ANALOG_VALUE:
|
||||
if (Analog_Value_Write_Property(&wp_data, &error_class,
|
||||
&error_code)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
} else {
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
case OBJECT_BINARY_VALUE:
|
||||
if (Binary_Value_Write_Property(&wp_data, &error_class,
|
||||
&error_code)) {
|
||||
len =
|
||||
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY);
|
||||
} else {
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id,
|
||||
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
|
||||
error_code);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
len =
|
||||
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||
error_class, error_code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
pdu_len += len;
|
||||
bytes_sent =
|
||||
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
|
||||
pdu_len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#ifndef HARDWARE_H
|
||||
#define HARDWARE_H
|
||||
|
||||
#if !defined(F_CPU)
|
||||
/* The processor clock frequency */
|
||||
#define F_CPU 7372800UL
|
||||
#endif
|
||||
|
||||
#if defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ASM__)
|
||||
#include <iom168.h>
|
||||
#else
|
||||
#if !defined(__AVR_ATmega168__)
|
||||
#error Firmware is configured for ATmega168 only (-mmcu=atmega168)
|
||||
#endif
|
||||
#endif
|
||||
#include "iar2gcc.h"
|
||||
#include "avr035.h"
|
||||
|
||||
#define LED_NPDU_INIT() BIT_SET(DDRD, DDD5)
|
||||
#define LED_NPDU_ON() BIT_CLEAR(PORTD, PD5)
|
||||
#define LED_NPDU_OFF() BIT_SET(PORTD, PD5)
|
||||
/* #define LED_NPDU PORTD_Bit5 */
|
||||
/* #define LED_NPDU_OFF() {LED_NPDU = false;} */
|
||||
/* #define LED_NPDU_ON() {LED_NPDU = true;} */
|
||||
|
||||
#define LED_GREEN_INIT() BIT_SET(DDRD, DDD4)
|
||||
#define LED_GREEN_ON() BIT_CLEAR(PORTD, PD4)
|
||||
#define LED_GREEN_OFF() BIT_SET(PORTD, PD4)
|
||||
|
||||
#endif
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#ifndef HARDWARE_H
|
||||
#define HARDWARE_H
|
||||
|
||||
#if !defined(F_CPU)
|
||||
/* The processor clock frequency */
|
||||
#define F_CPU 7372800UL
|
||||
#endif
|
||||
|
||||
#if defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ASM__)
|
||||
#include <iom168.h>
|
||||
#else
|
||||
#if !defined(__AVR_ATmega168__)
|
||||
#error Firmware is configured for ATmega168 only (-mmcu=atmega168)
|
||||
#endif
|
||||
#endif
|
||||
#include "iar2gcc.h"
|
||||
#include "avr035.h"
|
||||
|
||||
#define LED_NPDU_INIT() BIT_SET(DDRD, DDD5)
|
||||
#define LED_NPDU_ON() BIT_CLEAR(PORTD, PD5)
|
||||
#define LED_NPDU_OFF() BIT_SET(PORTD, PD5)
|
||||
/* #define LED_NPDU PORTD_Bit5 */
|
||||
/* #define LED_NPDU_OFF() {LED_NPDU = false;} */
|
||||
/* #define LED_NPDU_ON() {LED_NPDU = true;} */
|
||||
|
||||
#define LED_GREEN_INIT() BIT_SET(DDRD, DDD4)
|
||||
#define LED_GREEN_ON() BIT_CLEAR(PORTD, PD4)
|
||||
#define LED_GREEN_OFF() BIT_SET(PORTD, PD4)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,226 +1,226 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2007 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
#ifndef IAR2GCC_H
|
||||
#define IAR2GCC_H
|
||||
|
||||
#if !defined(F_CPU)
|
||||
#define F_CPU (7372800)
|
||||
#endif
|
||||
|
||||
/* IAR */
|
||||
#if defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ASM__)
|
||||
#include <inavr.h>
|
||||
#include <ioavr.h>
|
||||
/* BitValue is used alot in GCC examples */
|
||||
#define _BV(bit_num) (1 << (bit_num))
|
||||
|
||||
/* inline function */
|
||||
static inline void _delay_us(
|
||||
uint8_t microseconds)
|
||||
{
|
||||
do {
|
||||
__delay_cycles(F_CPU / 1000000UL);
|
||||
} while (microseconds--);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Input/Output Registers */
|
||||
#if defined(__GNUC__)
|
||||
#include <avr/io.h>
|
||||
|
||||
typedef struct {
|
||||
unsigned char bit0:1;
|
||||
unsigned char bit1:1;
|
||||
unsigned char bit2:1;
|
||||
unsigned char bit3:1;
|
||||
unsigned char bit4:1;
|
||||
unsigned char bit5:1;
|
||||
unsigned char bit6:1;
|
||||
unsigned char bit7:1;
|
||||
} BitRegisterType;
|
||||
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#endif
|
||||
|
||||
#ifndef false
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#define GPIO_BITREG(port,bitnum) \
|
||||
((volatile BitRegisterType*)_SFR_MEM_ADDR(port) \
|
||||
)->bit ## bitnum
|
||||
|
||||
#define PINA_Bit0 GPIO_BITREG(PINA,0)
|
||||
#define PINA_Bit1 GPIO_BITREG(PINA,1)
|
||||
#define PINA_Bit2 GPIO_BITREG(PINA,2)
|
||||
#define PINA_Bit3 GPIO_BITREG(PINA,3)
|
||||
#define PINA_Bit4 GPIO_BITREG(PINA,4)
|
||||
#define PINA_Bit5 GPIO_BITREG(PINA,5)
|
||||
#define PINA_Bit6 GPIO_BITREG(PINA,6)
|
||||
#define PINA_Bit7 GPIO_BITREG(PINA,7)
|
||||
|
||||
#define PORTA_Bit0 GPIO_BITREG(PORTA,0)
|
||||
#define PORTA_Bit1 GPIO_BITREG(PORTA,1)
|
||||
#define PORTA_Bit2 GPIO_BITREG(PORTA,2)
|
||||
#define PORTA_Bit3 GPIO_BITREG(PORTA,3)
|
||||
#define PORTA_Bit4 GPIO_BITREG(PORTA,4)
|
||||
#define PORTA_Bit5 GPIO_BITREG(PORTA,5)
|
||||
#define PORTA_Bit6 GPIO_BITREG(PORTA,6)
|
||||
#define PORTA_Bit7 GPIO_BITREG(PORTA,7)
|
||||
|
||||
#define PINB_Bit0 GPIO_BITREG(PINB,0)
|
||||
#define PINB_Bit1 GPIO_BITREG(PINB,1)
|
||||
#define PINB_Bit2 GPIO_BITREG(PINB,2)
|
||||
#define PINB_Bit3 GPIO_BITREG(PINB,3)
|
||||
#define PINB_Bit4 GPIO_BITREG(PINB,4)
|
||||
#define PINB_Bit5 GPIO_BITREG(PINB,5)
|
||||
#define PINB_Bit6 GPIO_BITREG(PINB,6)
|
||||
#define PINB_Bit7 GPIO_BITREG(PINB,7)
|
||||
|
||||
#define PORTB_Bit0 GPIO_BITREG(PORTB,0)
|
||||
#define PORTB_Bit1 GPIO_BITREG(PORTB,1)
|
||||
#define PORTB_Bit2 GPIO_BITREG(PORTB,2)
|
||||
#define PORTB_Bit3 GPIO_BITREG(PORTB,3)
|
||||
#define PORTB_Bit4 GPIO_BITREG(PORTB,4)
|
||||
#define PORTB_Bit5 GPIO_BITREG(PORTB,5)
|
||||
#define PORTB_Bit6 GPIO_BITREG(PORTB,6)
|
||||
#define PORTB_Bit7 GPIO_BITREG(PORTB,7)
|
||||
|
||||
#define PINC_Bit0 GPIO_BITREG(PINC,0)
|
||||
#define PINC_Bit1 GPIO_BITREG(PINC,1)
|
||||
#define PINC_Bit2 GPIO_BITREG(PINC,2)
|
||||
#define PINC_Bit3 GPIO_BITREG(PINC,3)
|
||||
#define PINC_Bit4 GPIO_BITREG(PINC,4)
|
||||
#define PINC_Bit5 GPIO_BITREG(PINC,5)
|
||||
#define PINC_Bit6 GPIO_BITREG(PINC,6)
|
||||
#define PINC_Bit7 GPIO_BITREG(PINC,7)
|
||||
|
||||
#define PORTC_Bit0 GPIO_BITREG(PORTC,0)
|
||||
#define PORTC_Bit1 GPIO_BITREG(PORTC,1)
|
||||
#define PORTC_Bit2 GPIO_BITREG(PORTC,2)
|
||||
#define PORTC_Bit3 GPIO_BITREG(PORTC,3)
|
||||
#define PORTC_Bit4 GPIO_BITREG(PORTC,4)
|
||||
#define PORTC_Bit5 GPIO_BITREG(PORTC,5)
|
||||
#define PORTC_Bit6 GPIO_BITREG(PORTC,6)
|
||||
#define PORTC_Bit7 GPIO_BITREG(PORTC,7)
|
||||
|
||||
#define PIND_Bit0 GPIO_BITREG(PIND,0)
|
||||
#define PIND_Bit1 GPIO_BITREG(PIND,1)
|
||||
#define PIND_Bit2 GPIO_BITREG(PIND,2)
|
||||
#define PIND_Bit3 GPIO_BITREG(PIND,3)
|
||||
#define PIND_Bit4 GPIO_BITREG(PIND,4)
|
||||
#define PIND_Bit5 GPIO_BITREG(PIND,5)
|
||||
#define PIND_Bit6 GPIO_BITREG(PIND,6)
|
||||
#define PIND_Bit7 GPIO_BITREG(PIND,7)
|
||||
|
||||
#define PORTD_Bit0 GPIO_BITREG(PORTD,0)
|
||||
#define PORTD_Bit1 GPIO_BITREG(PORTD,1)
|
||||
#define PORTD_Bit2 GPIO_BITREG(PORTD,2)
|
||||
#define PORTD_Bit3 GPIO_BITREG(PORTD,3)
|
||||
#define PORTD_Bit4 GPIO_BITREG(PORTD,4)
|
||||
#define PORTD_Bit5 GPIO_BITREG(PORTD,5)
|
||||
#define PORTD_Bit6 GPIO_BITREG(PORTD,6)
|
||||
#define PORTD_Bit7 GPIO_BITREG(PORTD,7)
|
||||
|
||||
#define GPIOR0_Bit0 GPIO_BITREG(GPIOR0,0)
|
||||
#define GPIOR0_Bit1 GPIO_BITREG(GPIOR0,1)
|
||||
#define GPIOR0_Bit2 GPIO_BITREG(GPIOR0,2)
|
||||
#define GPIOR0_Bit3 GPIO_BITREG(GPIOR0,3)
|
||||
#define GPIOR0_Bit4 GPIO_BITREG(GPIOR0,4)
|
||||
#define GPIOR0_Bit5 GPIO_BITREG(GPIOR0,5)
|
||||
#define GPIOR0_Bit6 GPIO_BITREG(GPIOR0,6)
|
||||
#define GPIOR0_Bit7 GPIO_BITREG(GPIOR0,7)
|
||||
|
||||
#define GPIOR1_Bit0 GPIO_BITREG(GPIOR1,0)
|
||||
#define GPIOR1_Bit1 GPIO_BITREG(GPIOR1,1)
|
||||
#define GPIOR1_Bit2 GPIO_BITREG(GPIOR1,2)
|
||||
#define GPIOR1_Bit3 GPIO_BITREG(GPIOR1,3)
|
||||
#define GPIOR1_Bit4 GPIO_BITREG(GPIOR1,4)
|
||||
#define GPIOR1_Bit5 GPIO_BITREG(GPIOR1,5)
|
||||
#define GPIOR1_Bit6 GPIO_BITREG(GPIOR1,6)
|
||||
#define GPIOR1_Bit7 GPIO_BITREG(GPIOR1,7)
|
||||
|
||||
#define GPIOR2_Bit0 GPIO_BITREG(GPIOR2,0)
|
||||
#define GPIOR2_Bit1 GPIO_BITREG(GPIOR2,1)
|
||||
#define GPIOR2_Bit2 GPIO_BITREG(GPIOR2,2)
|
||||
#define GPIOR2_Bit3 GPIO_BITREG(GPIOR2,3)
|
||||
#define GPIOR2_Bit4 GPIO_BITREG(GPIOR2,4)
|
||||
#define GPIOR2_Bit5 GPIO_BITREG(GPIOR2,5)
|
||||
#define GPIOR2_Bit6 GPIO_BITREG(GPIOR2,6)
|
||||
#define GPIOR2_Bit7 GPIO_BITREG(GPIOR2,7)
|
||||
|
||||
#endif
|
||||
|
||||
/* Global Interrupts */
|
||||
#if defined(__GNUC__)
|
||||
#define __enable_interrupt() sei()
|
||||
#define __disable_interrupt() cli()
|
||||
#endif
|
||||
|
||||
/* Interrupts */
|
||||
#if defined(__ICCAVR__)
|
||||
#define PRAGMA(x) _Pragma( #x )
|
||||
#define ISR(vec) PRAGMA( vector=vec ) __interrupt void handler_##vec(void)
|
||||
#endif
|
||||
#if defined(__GNUC__)
|
||||
#include <avr/interrupt.h>
|
||||
#endif
|
||||
|
||||
/* Flash */
|
||||
#if defined(__ICCAVR__)
|
||||
#define FLASH_DECLARE(x) __flash x
|
||||
#endif
|
||||
#if defined(__GNUC__)
|
||||
#define FLASH_DECLARE(x) x __attribute__((__progmem__))
|
||||
#endif
|
||||
|
||||
/* EEPROM */
|
||||
#if defined(__ICCAVR__)
|
||||
#define EEPROM_DECLARE(x) __eeprom x
|
||||
#endif
|
||||
#if defined(__GNUC__)
|
||||
#include <avr/eeprom.h>
|
||||
#define EEPROM_DECLARE(x) x __attribute__((section (".eeprom")))
|
||||
#endif
|
||||
|
||||
/* IAR intrinsic routines */
|
||||
#if defined(__GNUC__)
|
||||
/* FIXME: intrinsic routines: map to assembler for size/speed */
|
||||
#define __multiply_unsigned(x,y) ((x)*(y))
|
||||
/* FIXME: __root means to not optimize or strip */
|
||||
#define __root
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2007 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
#ifndef IAR2GCC_H
|
||||
#define IAR2GCC_H
|
||||
|
||||
#if !defined(F_CPU)
|
||||
#define F_CPU (7372800)
|
||||
#endif
|
||||
|
||||
/* IAR */
|
||||
#if defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ASM__)
|
||||
#include <inavr.h>
|
||||
#include <ioavr.h>
|
||||
/* BitValue is used alot in GCC examples */
|
||||
#define _BV(bit_num) (1 << (bit_num))
|
||||
|
||||
/* inline function */
|
||||
static inline void _delay_us(
|
||||
uint8_t microseconds)
|
||||
{
|
||||
do {
|
||||
__delay_cycles(F_CPU / 1000000UL);
|
||||
} while (microseconds--);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Input/Output Registers */
|
||||
#if defined(__GNUC__)
|
||||
#include <avr/io.h>
|
||||
|
||||
typedef struct {
|
||||
unsigned char bit0:1;
|
||||
unsigned char bit1:1;
|
||||
unsigned char bit2:1;
|
||||
unsigned char bit3:1;
|
||||
unsigned char bit4:1;
|
||||
unsigned char bit5:1;
|
||||
unsigned char bit6:1;
|
||||
unsigned char bit7:1;
|
||||
} BitRegisterType;
|
||||
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#endif
|
||||
|
||||
#ifndef false
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#define GPIO_BITREG(port,bitnum) \
|
||||
((volatile BitRegisterType*)_SFR_MEM_ADDR(port) \
|
||||
)->bit ## bitnum
|
||||
|
||||
#define PINA_Bit0 GPIO_BITREG(PINA,0)
|
||||
#define PINA_Bit1 GPIO_BITREG(PINA,1)
|
||||
#define PINA_Bit2 GPIO_BITREG(PINA,2)
|
||||
#define PINA_Bit3 GPIO_BITREG(PINA,3)
|
||||
#define PINA_Bit4 GPIO_BITREG(PINA,4)
|
||||
#define PINA_Bit5 GPIO_BITREG(PINA,5)
|
||||
#define PINA_Bit6 GPIO_BITREG(PINA,6)
|
||||
#define PINA_Bit7 GPIO_BITREG(PINA,7)
|
||||
|
||||
#define PORTA_Bit0 GPIO_BITREG(PORTA,0)
|
||||
#define PORTA_Bit1 GPIO_BITREG(PORTA,1)
|
||||
#define PORTA_Bit2 GPIO_BITREG(PORTA,2)
|
||||
#define PORTA_Bit3 GPIO_BITREG(PORTA,3)
|
||||
#define PORTA_Bit4 GPIO_BITREG(PORTA,4)
|
||||
#define PORTA_Bit5 GPIO_BITREG(PORTA,5)
|
||||
#define PORTA_Bit6 GPIO_BITREG(PORTA,6)
|
||||
#define PORTA_Bit7 GPIO_BITREG(PORTA,7)
|
||||
|
||||
#define PINB_Bit0 GPIO_BITREG(PINB,0)
|
||||
#define PINB_Bit1 GPIO_BITREG(PINB,1)
|
||||
#define PINB_Bit2 GPIO_BITREG(PINB,2)
|
||||
#define PINB_Bit3 GPIO_BITREG(PINB,3)
|
||||
#define PINB_Bit4 GPIO_BITREG(PINB,4)
|
||||
#define PINB_Bit5 GPIO_BITREG(PINB,5)
|
||||
#define PINB_Bit6 GPIO_BITREG(PINB,6)
|
||||
#define PINB_Bit7 GPIO_BITREG(PINB,7)
|
||||
|
||||
#define PORTB_Bit0 GPIO_BITREG(PORTB,0)
|
||||
#define PORTB_Bit1 GPIO_BITREG(PORTB,1)
|
||||
#define PORTB_Bit2 GPIO_BITREG(PORTB,2)
|
||||
#define PORTB_Bit3 GPIO_BITREG(PORTB,3)
|
||||
#define PORTB_Bit4 GPIO_BITREG(PORTB,4)
|
||||
#define PORTB_Bit5 GPIO_BITREG(PORTB,5)
|
||||
#define PORTB_Bit6 GPIO_BITREG(PORTB,6)
|
||||
#define PORTB_Bit7 GPIO_BITREG(PORTB,7)
|
||||
|
||||
#define PINC_Bit0 GPIO_BITREG(PINC,0)
|
||||
#define PINC_Bit1 GPIO_BITREG(PINC,1)
|
||||
#define PINC_Bit2 GPIO_BITREG(PINC,2)
|
||||
#define PINC_Bit3 GPIO_BITREG(PINC,3)
|
||||
#define PINC_Bit4 GPIO_BITREG(PINC,4)
|
||||
#define PINC_Bit5 GPIO_BITREG(PINC,5)
|
||||
#define PINC_Bit6 GPIO_BITREG(PINC,6)
|
||||
#define PINC_Bit7 GPIO_BITREG(PINC,7)
|
||||
|
||||
#define PORTC_Bit0 GPIO_BITREG(PORTC,0)
|
||||
#define PORTC_Bit1 GPIO_BITREG(PORTC,1)
|
||||
#define PORTC_Bit2 GPIO_BITREG(PORTC,2)
|
||||
#define PORTC_Bit3 GPIO_BITREG(PORTC,3)
|
||||
#define PORTC_Bit4 GPIO_BITREG(PORTC,4)
|
||||
#define PORTC_Bit5 GPIO_BITREG(PORTC,5)
|
||||
#define PORTC_Bit6 GPIO_BITREG(PORTC,6)
|
||||
#define PORTC_Bit7 GPIO_BITREG(PORTC,7)
|
||||
|
||||
#define PIND_Bit0 GPIO_BITREG(PIND,0)
|
||||
#define PIND_Bit1 GPIO_BITREG(PIND,1)
|
||||
#define PIND_Bit2 GPIO_BITREG(PIND,2)
|
||||
#define PIND_Bit3 GPIO_BITREG(PIND,3)
|
||||
#define PIND_Bit4 GPIO_BITREG(PIND,4)
|
||||
#define PIND_Bit5 GPIO_BITREG(PIND,5)
|
||||
#define PIND_Bit6 GPIO_BITREG(PIND,6)
|
||||
#define PIND_Bit7 GPIO_BITREG(PIND,7)
|
||||
|
||||
#define PORTD_Bit0 GPIO_BITREG(PORTD,0)
|
||||
#define PORTD_Bit1 GPIO_BITREG(PORTD,1)
|
||||
#define PORTD_Bit2 GPIO_BITREG(PORTD,2)
|
||||
#define PORTD_Bit3 GPIO_BITREG(PORTD,3)
|
||||
#define PORTD_Bit4 GPIO_BITREG(PORTD,4)
|
||||
#define PORTD_Bit5 GPIO_BITREG(PORTD,5)
|
||||
#define PORTD_Bit6 GPIO_BITREG(PORTD,6)
|
||||
#define PORTD_Bit7 GPIO_BITREG(PORTD,7)
|
||||
|
||||
#define GPIOR0_Bit0 GPIO_BITREG(GPIOR0,0)
|
||||
#define GPIOR0_Bit1 GPIO_BITREG(GPIOR0,1)
|
||||
#define GPIOR0_Bit2 GPIO_BITREG(GPIOR0,2)
|
||||
#define GPIOR0_Bit3 GPIO_BITREG(GPIOR0,3)
|
||||
#define GPIOR0_Bit4 GPIO_BITREG(GPIOR0,4)
|
||||
#define GPIOR0_Bit5 GPIO_BITREG(GPIOR0,5)
|
||||
#define GPIOR0_Bit6 GPIO_BITREG(GPIOR0,6)
|
||||
#define GPIOR0_Bit7 GPIO_BITREG(GPIOR0,7)
|
||||
|
||||
#define GPIOR1_Bit0 GPIO_BITREG(GPIOR1,0)
|
||||
#define GPIOR1_Bit1 GPIO_BITREG(GPIOR1,1)
|
||||
#define GPIOR1_Bit2 GPIO_BITREG(GPIOR1,2)
|
||||
#define GPIOR1_Bit3 GPIO_BITREG(GPIOR1,3)
|
||||
#define GPIOR1_Bit4 GPIO_BITREG(GPIOR1,4)
|
||||
#define GPIOR1_Bit5 GPIO_BITREG(GPIOR1,5)
|
||||
#define GPIOR1_Bit6 GPIO_BITREG(GPIOR1,6)
|
||||
#define GPIOR1_Bit7 GPIO_BITREG(GPIOR1,7)
|
||||
|
||||
#define GPIOR2_Bit0 GPIO_BITREG(GPIOR2,0)
|
||||
#define GPIOR2_Bit1 GPIO_BITREG(GPIOR2,1)
|
||||
#define GPIOR2_Bit2 GPIO_BITREG(GPIOR2,2)
|
||||
#define GPIOR2_Bit3 GPIO_BITREG(GPIOR2,3)
|
||||
#define GPIOR2_Bit4 GPIO_BITREG(GPIOR2,4)
|
||||
#define GPIOR2_Bit5 GPIO_BITREG(GPIOR2,5)
|
||||
#define GPIOR2_Bit6 GPIO_BITREG(GPIOR2,6)
|
||||
#define GPIOR2_Bit7 GPIO_BITREG(GPIOR2,7)
|
||||
|
||||
#endif
|
||||
|
||||
/* Global Interrupts */
|
||||
#if defined(__GNUC__)
|
||||
#define __enable_interrupt() sei()
|
||||
#define __disable_interrupt() cli()
|
||||
#endif
|
||||
|
||||
/* Interrupts */
|
||||
#if defined(__ICCAVR__)
|
||||
#define PRAGMA(x) _Pragma( #x )
|
||||
#define ISR(vec) PRAGMA( vector=vec ) __interrupt void handler_##vec(void)
|
||||
#endif
|
||||
#if defined(__GNUC__)
|
||||
#include <avr/interrupt.h>
|
||||
#endif
|
||||
|
||||
/* Flash */
|
||||
#if defined(__ICCAVR__)
|
||||
#define FLASH_DECLARE(x) __flash x
|
||||
#endif
|
||||
#if defined(__GNUC__)
|
||||
#define FLASH_DECLARE(x) x __attribute__((__progmem__))
|
||||
#endif
|
||||
|
||||
/* EEPROM */
|
||||
#if defined(__ICCAVR__)
|
||||
#define EEPROM_DECLARE(x) __eeprom x
|
||||
#endif
|
||||
#if defined(__GNUC__)
|
||||
#include <avr/eeprom.h>
|
||||
#define EEPROM_DECLARE(x) x __attribute__((section (".eeprom")))
|
||||
#endif
|
||||
|
||||
/* IAR intrinsic routines */
|
||||
#if defined(__GNUC__)
|
||||
/* FIXME: intrinsic routines: map to assembler for size/speed */
|
||||
#define __multiply_unsigned(x,y) ((x)*(y))
|
||||
/* FIXME: __root means to not optimize or strip */
|
||||
#define __root
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+122
-122
@@ -1,122 +1,122 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "hardware.h"
|
||||
#include "timer.h"
|
||||
#include "rs485.h"
|
||||
#include "datalink.h"
|
||||
#include "npdu.h"
|
||||
#include "txbuf.h"
|
||||
#include "iam.h"
|
||||
#include "device.h"
|
||||
#include "av.h"
|
||||
#include "handlers.h"
|
||||
|
||||
/* local version override */
|
||||
const char *BACnet_Version = "1.0";
|
||||
|
||||
/* For porting to IAR, see:
|
||||
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
|
||||
|
||||
/* dummy function - so we can use default demo handlers */
|
||||
bool dcc_communication_enabled(
|
||||
void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void init(
|
||||
void)
|
||||
{
|
||||
/* FIXME: Initialize the Clock Prescaler for ATmega8 */
|
||||
#if defined(__AVR_ATmega168__)
|
||||
/* The default CLKPSx bits are factory set to 0011 */
|
||||
/* Enbable the Clock Prescaler */
|
||||
CLKPR = _BV(CLKPCE);
|
||||
/* CLKPS3 CLKPS2 CLKPS1 CLKPS0 Clock Division Factor
|
||||
------ ------ ------ ------ ---------------------
|
||||
0 0 0 0 1
|
||||
0 0 0 1 2
|
||||
0 0 1 0 4
|
||||
0 0 1 1 8
|
||||
0 1 0 0 16
|
||||
0 1 0 1 32
|
||||
0 1 1 0 64
|
||||
0 1 1 1 128
|
||||
1 0 0 0 256
|
||||
1 x x x Reserved
|
||||
*/
|
||||
/* Set the CLKPS3..0 bits to Prescaler of 1 */
|
||||
CLKPR = 0;
|
||||
#endif
|
||||
/* Initialize I/O ports */
|
||||
/* For Port DDRx (Data Direction) Input=0, Output=1 */
|
||||
/* For Port PORTx (Bit Value) TriState=0, High=1 */
|
||||
DDRB = 0;
|
||||
PORTB = 0;
|
||||
DDRC = 0;
|
||||
PORTC = 0;
|
||||
DDRD = 0;
|
||||
PORTD = 0;
|
||||
|
||||
/* Configure the watchdog timer - Disabled for testing */
|
||||
#if defined(__AVR_ATmega168__)
|
||||
BIT_CLEAR(MCUSR, WDRF);
|
||||
WDTCSR = 0;
|
||||
#else
|
||||
BIT_CLEAR(MCUCSR, WDRF);
|
||||
WDTCR = 0;
|
||||
#endif
|
||||
|
||||
/* Configure Specialized Hardware */
|
||||
RS485_Initialize();
|
||||
RS485_Set_Baud_Rate(38400);
|
||||
/* Configure Timer0 for millisecond timer */
|
||||
timer_init();
|
||||
/* Enable global interrupts */
|
||||
__enable_interrupt();
|
||||
}
|
||||
|
||||
static uint8_t PDUBuffer[MAX_MPDU];
|
||||
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
BACNET_ADDRESS src; /* source address */
|
||||
|
||||
init();
|
||||
datalink_init(NULL);
|
||||
for (;;) {
|
||||
/* other tasks */
|
||||
/* BACnet handling */
|
||||
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
|
||||
if (pdu_len) {
|
||||
npdu_handler(&src, &PDUBuffer[0], pdu_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "hardware.h"
|
||||
#include "timer.h"
|
||||
#include "rs485.h"
|
||||
#include "datalink.h"
|
||||
#include "npdu.h"
|
||||
#include "txbuf.h"
|
||||
#include "iam.h"
|
||||
#include "device.h"
|
||||
#include "av.h"
|
||||
#include "handlers.h"
|
||||
|
||||
/* local version override */
|
||||
const char *BACnet_Version = "1.0";
|
||||
|
||||
/* For porting to IAR, see:
|
||||
http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC/IarToAvrgcc*/
|
||||
|
||||
/* dummy function - so we can use default demo handlers */
|
||||
bool dcc_communication_enabled(
|
||||
void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void init(
|
||||
void)
|
||||
{
|
||||
/* FIXME: Initialize the Clock Prescaler for ATmega8 */
|
||||
#if defined(__AVR_ATmega168__)
|
||||
/* The default CLKPSx bits are factory set to 0011 */
|
||||
/* Enbable the Clock Prescaler */
|
||||
CLKPR = _BV(CLKPCE);
|
||||
/* CLKPS3 CLKPS2 CLKPS1 CLKPS0 Clock Division Factor
|
||||
------ ------ ------ ------ ---------------------
|
||||
0 0 0 0 1
|
||||
0 0 0 1 2
|
||||
0 0 1 0 4
|
||||
0 0 1 1 8
|
||||
0 1 0 0 16
|
||||
0 1 0 1 32
|
||||
0 1 1 0 64
|
||||
0 1 1 1 128
|
||||
1 0 0 0 256
|
||||
1 x x x Reserved
|
||||
*/
|
||||
/* Set the CLKPS3..0 bits to Prescaler of 1 */
|
||||
CLKPR = 0;
|
||||
#endif
|
||||
/* Initialize I/O ports */
|
||||
/* For Port DDRx (Data Direction) Input=0, Output=1 */
|
||||
/* For Port PORTx (Bit Value) TriState=0, High=1 */
|
||||
DDRB = 0;
|
||||
PORTB = 0;
|
||||
DDRC = 0;
|
||||
PORTC = 0;
|
||||
DDRD = 0;
|
||||
PORTD = 0;
|
||||
|
||||
/* Configure the watchdog timer - Disabled for testing */
|
||||
#if defined(__AVR_ATmega168__)
|
||||
BIT_CLEAR(MCUSR, WDRF);
|
||||
WDTCSR = 0;
|
||||
#else
|
||||
BIT_CLEAR(MCUCSR, WDRF);
|
||||
WDTCR = 0;
|
||||
#endif
|
||||
|
||||
/* Configure Specialized Hardware */
|
||||
RS485_Initialize();
|
||||
RS485_Set_Baud_Rate(38400);
|
||||
/* Configure Timer0 for millisecond timer */
|
||||
timer_init();
|
||||
/* Enable global interrupts */
|
||||
__enable_interrupt();
|
||||
}
|
||||
|
||||
static uint8_t PDUBuffer[MAX_MPDU];
|
||||
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
uint16_t pdu_len = 0;
|
||||
BACNET_ADDRESS src; /* source address */
|
||||
|
||||
init();
|
||||
datalink_init(NULL);
|
||||
for (;;) {
|
||||
/* other tasks */
|
||||
/* BACnet handling */
|
||||
pdu_len = datalink_receive(&src, &PDUBuffer[0], sizeof(PDUBuffer), 0);
|
||||
if (pdu_len) {
|
||||
npdu_handler(&src, &PDUBuffer[0], pdu_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+292
-292
@@ -1,292 +1,292 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/* The module handles sending data out the RS-485 port */
|
||||
/* and handles receiving data from the RS-485 port. */
|
||||
/* Customize this file for your specific hardware */
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
/*#include "mstp.h" */
|
||||
|
||||
/* This file has been customized for use with ATMEGA168 */
|
||||
#if defined(__AVR_ATmega168__)
|
||||
/* USART defines for RS-485 port */
|
||||
#define UCSRB UCSR0B
|
||||
#define TXEN TXEN0
|
||||
#define RXEN RXEN0
|
||||
#define UCSRC UCSR0C
|
||||
#define UCSZ1 UCSZ01
|
||||
#define UCSZ0 UCSZ00
|
||||
#define UCSRA UCSR0A
|
||||
#define U2X U2X0
|
||||
#define UBRRL UBRR0
|
||||
#define UCSRA UCSR0A
|
||||
#define UDRE UDRE0
|
||||
#define UDR UDR0
|
||||
#define TXC TXC0
|
||||
#define FE FE0
|
||||
#define DOR DOR0
|
||||
#define UPE UPE0
|
||||
#define DOR DOR0
|
||||
#define RXC RXC0
|
||||
#endif
|
||||
|
||||
#include "hardware.h"
|
||||
#include "timer.h"
|
||||
|
||||
/* baud rate */
|
||||
static uint32_t RS485_Baud;
|
||||
|
||||
/* The minimum time after the end of the stop bit of the final octet of a */
|
||||
/* received frame before a node may enable its EIA-485 driver: 40 bit times. */
|
||||
/* At 9600 baud, 40 bit times would be about 4.166 milliseconds */
|
||||
/* At 19200 baud, 40 bit times would be about 2.083 milliseconds */
|
||||
/* At 38400 baud, 40 bit times would be about 1.041 milliseconds */
|
||||
/* At 57600 baud, 40 bit times would be about 0.694 milliseconds */
|
||||
/* At 76800 baud, 40 bit times would be about 0.520 milliseconds */
|
||||
/* At 115200 baud, 40 bit times would be about 0.347 milliseconds */
|
||||
/* 40 bits is 4 octets including a start and stop bit with each octet */
|
||||
#define Tturnaround (40UL)
|
||||
/* turnaround_time_milliseconds = (Tturnaround*1000UL)/RS485_Baud; */
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
|
||||
* receive mode.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Initialize(
|
||||
void)
|
||||
{
|
||||
/* enable Transmit and Receive */
|
||||
UCSRB = _BV(TXEN) | _BV(RXEN);
|
||||
|
||||
/* Set USART Control and Status Register n C */
|
||||
/* Asynchronous USART 8-bit data, No parity, 1 stop */
|
||||
/* Set USART Mode Select: UMSELn1 UMSELn0 = 00 for Asynchronous USART */
|
||||
/* Set Parity Mode: UPMn1 UPMn0 = 00 for Parity Disabled */
|
||||
/* Set Stop Bit Select: USBSn = 0 for 1 stop bit */
|
||||
/* Set Character Size: UCSZn2 UCSZn1 UCSZn0 = 011 for 8-bit */
|
||||
/* Clock Polarity: UCPOLn = 0 when asynchronous mode is used. */
|
||||
UCSRC = _BV(UCSZ1) | _BV(UCSZ0);
|
||||
#if defined(__AVR_ATmega168__)
|
||||
/* Clear Power Reduction USART0 */
|
||||
BIT_CLEAR(PRR, PRUSART0);
|
||||
#endif
|
||||
/* Use port PD2 for RTS - enable and disable of Transceiver Tx/Rx */
|
||||
/* Set port bit as Output - initially receiving */
|
||||
BIT_CLEAR(PORTD, PD2);
|
||||
BIT_SET(DDRD, DDD2);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Baud_Rate(
|
||||
void)
|
||||
{
|
||||
return RS485_Baud;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Sets the baud rate for the chip USART
|
||||
* RETURN: true if valid baud rate
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Set_Baud_Rate(
|
||||
uint32_t baud)
|
||||
{
|
||||
bool valid = true;
|
||||
|
||||
switch (baud) {
|
||||
case 9600:
|
||||
case 19200:
|
||||
case 38400:
|
||||
case 57600:
|
||||
case 76800:
|
||||
case 115200:
|
||||
RS485_Baud = baud;
|
||||
/* 2x speed mode */
|
||||
BIT_SET(UCSRA, U2X);
|
||||
/* configure baud rate */
|
||||
UBRRL = (F_CPU / (8UL * RS485_Baud)) - 1;
|
||||
/* FIXME: store the baud rate */
|
||||
break;
|
||||
default:
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Waits on the SilenceTimer for 40 bits.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Turnaround_Delay(
|
||||
void)
|
||||
{
|
||||
uint16_t turnaround_time;
|
||||
|
||||
/* delay after reception before trasmitting - per MS/TP spec */
|
||||
/* wait a minimum 40 bit times since reception */
|
||||
/* at least 1 ms for errors: rounding, clock tick */
|
||||
turnaround_time = 1 + ((Tturnaround * 1000UL) / RS485_Baud);
|
||||
while (!timer_silence_elapsed(turnaround_time)) {
|
||||
/* do nothing - wait for timer to increment */
|
||||
};
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Enable or disable the transmitter
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Transmitter_Enable(
|
||||
bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
BIT_SET(PORTD, PD2);
|
||||
} else {
|
||||
BIT_CLEAR(PORTD, PD2);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Send some data and wait until it is sent
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Send_Data(
|
||||
uint8_t * buffer, /* data to send */
|
||||
uint16_t nbytes)
|
||||
{ /* number of bytes of data */
|
||||
while (nbytes) {
|
||||
while (!BIT_CHECK(UCSRA, UDRE)) {
|
||||
/* do nothing - wait until Tx buffer is empty */
|
||||
}
|
||||
/* Send the data byte */
|
||||
UDR = *buffer;
|
||||
buffer++;
|
||||
nbytes--;
|
||||
}
|
||||
/* was the frame sent? */
|
||||
while (!BIT_CHECK(UCSRA, TXC)) {
|
||||
/* do nothing - wait until the entire frame in the
|
||||
Transmit Shift Register has been shifted out */
|
||||
}
|
||||
/* Clear the Transmit Complete flag by writing a one to it. */
|
||||
BIT_SET(UCSRA, TXC);
|
||||
/* per MSTP spec, sort of */
|
||||
timer_silence_reset();
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Return true if a framing or overrun error is present
|
||||
* RETURN: true if error
|
||||
* ALGORITHM: autobaud - if there are a lot of errors, switch baud rate
|
||||
* NOTES: Clears any error flags.
|
||||
*****************************************************************************/
|
||||
bool RS485_ReceiveError(
|
||||
void)
|
||||
{
|
||||
bool ReceiveError = false;
|
||||
uint8_t dummy_data;
|
||||
|
||||
/* check for framing error */
|
||||
#if 0
|
||||
if (BIT_CHECK(UCSRA, FE0)) {
|
||||
/* FIXME: how do I clear the error flags? */
|
||||
BITMASK_CLEAR(UCSRA, (_BV(FE) | _BV(DOR) | _BV(UPE)));
|
||||
ReceiveError = true;
|
||||
}
|
||||
#endif
|
||||
/* check for overrun error */
|
||||
if (BIT_CHECK(UCSRA, DOR)) {
|
||||
/* flush the receive buffer */
|
||||
do {
|
||||
dummy_data = UDR;
|
||||
} while (BIT_CHECK(UCSRA, RXC));
|
||||
ReceiveError = true;
|
||||
}
|
||||
|
||||
return ReceiveError;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Return true if data is available
|
||||
* RETURN: true if data is available, with the data in the parameter set
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_DataAvailable(
|
||||
uint8_t * data)
|
||||
{
|
||||
bool DataAvailable = false;
|
||||
|
||||
/* check for data */
|
||||
if (BIT_CHECK(UCSRA, RXC)) {
|
||||
*data = UDR;
|
||||
DataAvailable = true;
|
||||
}
|
||||
|
||||
return DataAvailable;
|
||||
}
|
||||
|
||||
#ifdef TEST_RS485
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
unsigned i = 0;
|
||||
uint8_t DataRegister;
|
||||
|
||||
RS485_Set_Baud_Rate(38400);
|
||||
RS485_Initialize();
|
||||
/* receive task */
|
||||
for (;;) {
|
||||
if (RS485_ReceiveError()) {
|
||||
fprintf(stderr, "ERROR ");
|
||||
} else if (RS485_DataAvailable(&DataRegister)) {
|
||||
fprintf(stderr, "%02X ", DataRegister);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* TEST_RS485 */
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/* The module handles sending data out the RS-485 port */
|
||||
/* and handles receiving data from the RS-485 port. */
|
||||
/* Customize this file for your specific hardware */
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
/*#include "mstp.h" */
|
||||
|
||||
/* This file has been customized for use with ATMEGA168 */
|
||||
#if defined(__AVR_ATmega168__)
|
||||
/* USART defines for RS-485 port */
|
||||
#define UCSRB UCSR0B
|
||||
#define TXEN TXEN0
|
||||
#define RXEN RXEN0
|
||||
#define UCSRC UCSR0C
|
||||
#define UCSZ1 UCSZ01
|
||||
#define UCSZ0 UCSZ00
|
||||
#define UCSRA UCSR0A
|
||||
#define U2X U2X0
|
||||
#define UBRRL UBRR0
|
||||
#define UCSRA UCSR0A
|
||||
#define UDRE UDRE0
|
||||
#define UDR UDR0
|
||||
#define TXC TXC0
|
||||
#define FE FE0
|
||||
#define DOR DOR0
|
||||
#define UPE UPE0
|
||||
#define DOR DOR0
|
||||
#define RXC RXC0
|
||||
#endif
|
||||
|
||||
#include "hardware.h"
|
||||
#include "timer.h"
|
||||
|
||||
/* baud rate */
|
||||
static uint32_t RS485_Baud;
|
||||
|
||||
/* The minimum time after the end of the stop bit of the final octet of a */
|
||||
/* received frame before a node may enable its EIA-485 driver: 40 bit times. */
|
||||
/* At 9600 baud, 40 bit times would be about 4.166 milliseconds */
|
||||
/* At 19200 baud, 40 bit times would be about 2.083 milliseconds */
|
||||
/* At 38400 baud, 40 bit times would be about 1.041 milliseconds */
|
||||
/* At 57600 baud, 40 bit times would be about 0.694 milliseconds */
|
||||
/* At 76800 baud, 40 bit times would be about 0.520 milliseconds */
|
||||
/* At 115200 baud, 40 bit times would be about 0.347 milliseconds */
|
||||
/* 40 bits is 4 octets including a start and stop bit with each octet */
|
||||
#define Tturnaround (40UL)
|
||||
/* turnaround_time_milliseconds = (Tturnaround*1000UL)/RS485_Baud; */
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Initializes the RS485 hardware and variables, and starts in
|
||||
* receive mode.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Initialize(
|
||||
void)
|
||||
{
|
||||
/* enable Transmit and Receive */
|
||||
UCSRB = _BV(TXEN) | _BV(RXEN);
|
||||
|
||||
/* Set USART Control and Status Register n C */
|
||||
/* Asynchronous USART 8-bit data, No parity, 1 stop */
|
||||
/* Set USART Mode Select: UMSELn1 UMSELn0 = 00 for Asynchronous USART */
|
||||
/* Set Parity Mode: UPMn1 UPMn0 = 00 for Parity Disabled */
|
||||
/* Set Stop Bit Select: USBSn = 0 for 1 stop bit */
|
||||
/* Set Character Size: UCSZn2 UCSZn1 UCSZn0 = 011 for 8-bit */
|
||||
/* Clock Polarity: UCPOLn = 0 when asynchronous mode is used. */
|
||||
UCSRC = _BV(UCSZ1) | _BV(UCSZ0);
|
||||
#if defined(__AVR_ATmega168__)
|
||||
/* Clear Power Reduction USART0 */
|
||||
BIT_CLEAR(PRR, PRUSART0);
|
||||
#endif
|
||||
/* Use port PD2 for RTS - enable and disable of Transceiver Tx/Rx */
|
||||
/* Set port bit as Output - initially receiving */
|
||||
BIT_CLEAR(PORTD, PD2);
|
||||
BIT_SET(DDRD, DDD2);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Returns the baud rate that we are currently running at
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
uint32_t RS485_Get_Baud_Rate(
|
||||
void)
|
||||
{
|
||||
return RS485_Baud;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Sets the baud rate for the chip USART
|
||||
* RETURN: true if valid baud rate
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_Set_Baud_Rate(
|
||||
uint32_t baud)
|
||||
{
|
||||
bool valid = true;
|
||||
|
||||
switch (baud) {
|
||||
case 9600:
|
||||
case 19200:
|
||||
case 38400:
|
||||
case 57600:
|
||||
case 76800:
|
||||
case 115200:
|
||||
RS485_Baud = baud;
|
||||
/* 2x speed mode */
|
||||
BIT_SET(UCSRA, U2X);
|
||||
/* configure baud rate */
|
||||
UBRRL = (F_CPU / (8UL * RS485_Baud)) - 1;
|
||||
/* FIXME: store the baud rate */
|
||||
break;
|
||||
default:
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Waits on the SilenceTimer for 40 bits.
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Turnaround_Delay(
|
||||
void)
|
||||
{
|
||||
uint16_t turnaround_time;
|
||||
|
||||
/* delay after reception before trasmitting - per MS/TP spec */
|
||||
/* wait a minimum 40 bit times since reception */
|
||||
/* at least 1 ms for errors: rounding, clock tick */
|
||||
turnaround_time = 1 + ((Tturnaround * 1000UL) / RS485_Baud);
|
||||
while (!timer_silence_elapsed(turnaround_time)) {
|
||||
/* do nothing - wait for timer to increment */
|
||||
};
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Enable or disable the transmitter
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Transmitter_Enable(
|
||||
bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
BIT_SET(PORTD, PD2);
|
||||
} else {
|
||||
BIT_CLEAR(PORTD, PD2);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Send some data and wait until it is sent
|
||||
* RETURN: none
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
void RS485_Send_Data(
|
||||
uint8_t * buffer, /* data to send */
|
||||
uint16_t nbytes)
|
||||
{ /* number of bytes of data */
|
||||
while (nbytes) {
|
||||
while (!BIT_CHECK(UCSRA, UDRE)) {
|
||||
/* do nothing - wait until Tx buffer is empty */
|
||||
}
|
||||
/* Send the data byte */
|
||||
UDR = *buffer;
|
||||
buffer++;
|
||||
nbytes--;
|
||||
}
|
||||
/* was the frame sent? */
|
||||
while (!BIT_CHECK(UCSRA, TXC)) {
|
||||
/* do nothing - wait until the entire frame in the
|
||||
Transmit Shift Register has been shifted out */
|
||||
}
|
||||
/* Clear the Transmit Complete flag by writing a one to it. */
|
||||
BIT_SET(UCSRA, TXC);
|
||||
/* per MSTP spec, sort of */
|
||||
timer_silence_reset();
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Return true if a framing or overrun error is present
|
||||
* RETURN: true if error
|
||||
* ALGORITHM: autobaud - if there are a lot of errors, switch baud rate
|
||||
* NOTES: Clears any error flags.
|
||||
*****************************************************************************/
|
||||
bool RS485_ReceiveError(
|
||||
void)
|
||||
{
|
||||
bool ReceiveError = false;
|
||||
uint8_t dummy_data;
|
||||
|
||||
/* check for framing error */
|
||||
#if 0
|
||||
if (BIT_CHECK(UCSRA, FE0)) {
|
||||
/* FIXME: how do I clear the error flags? */
|
||||
BITMASK_CLEAR(UCSRA, (_BV(FE) | _BV(DOR) | _BV(UPE)));
|
||||
ReceiveError = true;
|
||||
}
|
||||
#endif
|
||||
/* check for overrun error */
|
||||
if (BIT_CHECK(UCSRA, DOR)) {
|
||||
/* flush the receive buffer */
|
||||
do {
|
||||
dummy_data = UDR;
|
||||
} while (BIT_CHECK(UCSRA, RXC));
|
||||
ReceiveError = true;
|
||||
}
|
||||
|
||||
return ReceiveError;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* DESCRIPTION: Return true if data is available
|
||||
* RETURN: true if data is available, with the data in the parameter set
|
||||
* ALGORITHM: none
|
||||
* NOTES: none
|
||||
*****************************************************************************/
|
||||
bool RS485_DataAvailable(
|
||||
uint8_t * data)
|
||||
{
|
||||
bool DataAvailable = false;
|
||||
|
||||
/* check for data */
|
||||
if (BIT_CHECK(UCSRA, RXC)) {
|
||||
*data = UDR;
|
||||
DataAvailable = true;
|
||||
}
|
||||
|
||||
return DataAvailable;
|
||||
}
|
||||
|
||||
#ifdef TEST_RS485
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
unsigned i = 0;
|
||||
uint8_t DataRegister;
|
||||
|
||||
RS485_Set_Baud_Rate(38400);
|
||||
RS485_Initialize();
|
||||
/* receive task */
|
||||
for (;;) {
|
||||
if (RS485_ReceiveError()) {
|
||||
fprintf(stderr, "ERROR ");
|
||||
} else if (RS485_DataAvailable(&DataRegister)) {
|
||||
fprintf(stderr, "%02X ", DataRegister);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* TEST_RS485 */
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2004 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307
|
||||
USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#ifndef RS485_H
|
||||
#define RS485_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void RS485_Initialize(
|
||||
void);
|
||||
|
||||
void RS485_Transmitter_Enable(
|
||||
bool enable);
|
||||
|
||||
void RS485_Send_Data(
|
||||
uint8_t * buffer, /* data to send */
|
||||
uint16_t nbytes); /* number of bytes of data */
|
||||
|
||||
bool RS485_ReceiveError(
|
||||
void);
|
||||
bool RS485_DataAvailable(
|
||||
uint8_t * data);
|
||||
|
||||
void RS485_Turnaround_Delay(
|
||||
void);
|
||||
uint32_t RS485_Get_Baud_Rate(
|
||||
void);
|
||||
bool RS485_Set_Baud_Rate(
|
||||
uint32_t baud);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2004 Steve Karg
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307
|
||||
USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#ifndef RS485_H
|
||||
#define RS485_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void RS485_Initialize(
|
||||
void);
|
||||
|
||||
void RS485_Transmitter_Enable(
|
||||
bool enable);
|
||||
|
||||
void RS485_Send_Data(
|
||||
uint8_t * buffer, /* data to send */
|
||||
uint16_t nbytes); /* number of bytes of data */
|
||||
|
||||
bool RS485_ReceiveError(
|
||||
void);
|
||||
bool RS485_DataAvailable(
|
||||
uint8_t * data);
|
||||
|
||||
void RS485_Turnaround_Delay(
|
||||
void);
|
||||
uint32_t RS485_Get_Baud_Rate(
|
||||
void);
|
||||
bool RS485_Set_Baud_Rate(
|
||||
uint32_t baud);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
#ifndef STDBOOL_H
|
||||
#define STDBOOL_H
|
||||
|
||||
/* C99 Boolean types for compilers without C99 support */
|
||||
|
||||
#ifndef __cplusplus
|
||||
/* typedef char _Bool; */
|
||||
#ifndef bool
|
||||
#define bool _Bool
|
||||
#endif
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#endif
|
||||
#ifndef false
|
||||
#define false 0
|
||||
#endif
|
||||
#define __bool_true_false_are_defined 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#ifndef STDBOOL_H
|
||||
#define STDBOOL_H
|
||||
|
||||
/* C99 Boolean types for compilers without C99 support */
|
||||
|
||||
#ifndef __cplusplus
|
||||
/* typedef char _Bool; */
|
||||
#ifndef bool
|
||||
#define bool _Bool
|
||||
#endif
|
||||
#ifndef true
|
||||
#define true 1
|
||||
#endif
|
||||
#ifndef false
|
||||
#define false 0
|
||||
#endif
|
||||
#define __bool_true_false_are_defined 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/* Defines the standard integer types that are used in code */
|
||||
|
||||
#ifndef STDINT_H
|
||||
#define STDINT_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef unsigned char uint8_t; /* 1 byte 0 to 255 */
|
||||
typedef signed char int8_t; /* 1 byte -127 to 127 */
|
||||
typedef unsigned short uint16_t; /* 2 bytes 0 to 65535 */
|
||||
typedef signed short int16_t; /* 2 bytes -32767 to 32767 */
|
||||
typedef unsigned long uint32_t; /* 4 bytes 0 to 4294967295 */
|
||||
typedef signed long int32_t; /* 4 bytes -2147483647 to 2147483647 */
|
||||
|
||||
#endif /* STDINT_H */
|
||||
/* Defines the standard integer types that are used in code */
|
||||
|
||||
#ifndef STDINT_H
|
||||
#define STDINT_H 1
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
typedef unsigned char uint8_t; /* 1 byte 0 to 255 */
|
||||
typedef signed char int8_t; /* 1 byte -127 to 127 */
|
||||
typedef unsigned short uint16_t; /* 2 bytes 0 to 65535 */
|
||||
typedef signed short int16_t; /* 2 bytes -32767 to 32767 */
|
||||
typedef unsigned long uint32_t; /* 4 bytes 0 to 4294967295 */
|
||||
typedef signed long int32_t; /* 4 bytes -2147483647 to 2147483647 */
|
||||
|
||||
#endif /* STDINT_H */
|
||||
|
||||
+110
-109
@@ -1,109 +1,110 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "hardware.h"
|
||||
|
||||
/* This module is a 1 millisecond timer */
|
||||
|
||||
/* Prescaling: 1, 8, 64, 256, 1024 */
|
||||
#define TIMER_PRESCALER 64
|
||||
/* Count: Timer0 counts up to 0xFF and then signals overflow */
|
||||
#define TIMER_TICKS (F_CPU/TIMER_PRESCALER/1000)
|
||||
#if (TIMER_TICKS > 0xFF)
|
||||
#error Timer Prescaler value is too small
|
||||
#endif
|
||||
#define TIMER_COUNT (0xFF-TIMER_TICKS)
|
||||
/* millisecond timer count */
|
||||
static volatile uint16_t Timer_Silence;
|
||||
|
||||
/* FIXME: Configure the Timer */
|
||||
void timer_init(
|
||||
void)
|
||||
{
|
||||
/* Normal Operation */
|
||||
TCCR1A = 0;
|
||||
/* CSn2 CSn1 CSn0 Description
|
||||
---- ---- ---- -----------
|
||||
0 0 0 No Clock Source
|
||||
0 0 1 No prescaling
|
||||
0 1 0 CLKio/8
|
||||
0 1 1 CLKio/64
|
||||
1 0 0 CLKio/256
|
||||
1 0 1 CLKio/1024
|
||||
1 1 0 Falling Edge of T0 (external)
|
||||
1 1 1 Rising Edge of T0 (external)
|
||||
*/
|
||||
#if defined(__AVR_ATmega168__)
|
||||
TCCR0B = _BV(CS01) | _BV(CS00);
|
||||
/* Clear any TOV1 Flag set when the timer overflowed */
|
||||
BIT_CLEAR(TIFR0, TOV0);
|
||||
/* Initial value */
|
||||
TCNT0 = TIMER_COUNT;
|
||||
/* Enable the overflow interrupt */
|
||||
BIT_SET(TIMSK0, TOIE0);
|
||||
/* Clear the Power Reduction Timer/Counter0 */
|
||||
BIT_CLEAR(PRR, PRTIM0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Timer interupt */
|
||||
/* note: Global interupts must be enabled - sei() */
|
||||
/* Timer Overflowed! Increment the time. */
|
||||
ISR(TIMER0_OVF_vect)
|
||||
{
|
||||
/* Set the counter for the next interrupt */
|
||||
TCNT0 = TIMER_COUNT;
|
||||
/* Overflow Flag is automatically cleared */
|
||||
/* Update the global timer */
|
||||
Timer_Silence++;
|
||||
}
|
||||
|
||||
/* return true if time has expired */
|
||||
bool timer_silence_elapsed(
|
||||
uint16_t value)
|
||||
{
|
||||
bool status = false;
|
||||
uint8_t sreg;
|
||||
|
||||
sreg = SREG;
|
||||
__disable_interrupt();
|
||||
if (Timer_Silence >= value) {
|
||||
status = true;
|
||||
}
|
||||
SREG = sreg;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void timer_silence_reset(void)
|
||||
{
|
||||
uint8_t sreg;
|
||||
|
||||
sreg = SREG;
|
||||
__disable_interrupt();
|
||||
Timer_Silence = 0;
|
||||
SREG = sreg;
|
||||
}
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "hardware.h"
|
||||
|
||||
/* This module is a 1 millisecond timer */
|
||||
|
||||
/* Prescaling: 1, 8, 64, 256, 1024 */
|
||||
#define TIMER_PRESCALER 64
|
||||
/* Count: Timer0 counts up to 0xFF and then signals overflow */
|
||||
#define TIMER_TICKS (F_CPU/TIMER_PRESCALER/1000)
|
||||
#if (TIMER_TICKS > 0xFF)
|
||||
#error Timer Prescaler value is too small
|
||||
#endif
|
||||
#define TIMER_COUNT (0xFF-TIMER_TICKS)
|
||||
/* millisecond timer count */
|
||||
static volatile uint16_t Timer_Silence;
|
||||
|
||||
/* FIXME: Configure the Timer */
|
||||
void timer_init(
|
||||
void)
|
||||
{
|
||||
/* Normal Operation */
|
||||
TCCR1A = 0;
|
||||
/* CSn2 CSn1 CSn0 Description
|
||||
---- ---- ---- -----------
|
||||
0 0 0 No Clock Source
|
||||
0 0 1 No prescaling
|
||||
0 1 0 CLKio/8
|
||||
0 1 1 CLKio/64
|
||||
1 0 0 CLKio/256
|
||||
1 0 1 CLKio/1024
|
||||
1 1 0 Falling Edge of T0 (external)
|
||||
1 1 1 Rising Edge of T0 (external)
|
||||
*/
|
||||
#if defined(__AVR_ATmega168__)
|
||||
TCCR0B = _BV(CS01) | _BV(CS00);
|
||||
/* Clear any TOV1 Flag set when the timer overflowed */
|
||||
BIT_CLEAR(TIFR0, TOV0);
|
||||
/* Initial value */
|
||||
TCNT0 = TIMER_COUNT;
|
||||
/* Enable the overflow interrupt */
|
||||
BIT_SET(TIMSK0, TOIE0);
|
||||
/* Clear the Power Reduction Timer/Counter0 */
|
||||
BIT_CLEAR(PRR, PRTIM0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Timer interupt */
|
||||
/* note: Global interupts must be enabled - sei() */
|
||||
/* Timer Overflowed! Increment the time. */
|
||||
ISR(TIMER0_OVF_vect)
|
||||
{
|
||||
/* Set the counter for the next interrupt */
|
||||
TCNT0 = TIMER_COUNT;
|
||||
/* Overflow Flag is automatically cleared */
|
||||
/* Update the global timer */
|
||||
Timer_Silence++;
|
||||
}
|
||||
|
||||
/* return true if time has expired */
|
||||
bool timer_silence_elapsed(
|
||||
uint16_t value)
|
||||
{
|
||||
bool status = false;
|
||||
uint8_t sreg;
|
||||
|
||||
sreg = SREG;
|
||||
__disable_interrupt();
|
||||
if (Timer_Silence >= value) {
|
||||
status = true;
|
||||
}
|
||||
SREG = sreg;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void timer_silence_reset(
|
||||
void)
|
||||
{
|
||||
uint8_t sreg;
|
||||
|
||||
sreg = SREG;
|
||||
__disable_interrupt();
|
||||
Timer_Silence = 0;
|
||||
SREG = sreg;
|
||||
}
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void timer_init(
|
||||
void);
|
||||
bool timer_silence_elapsed(
|
||||
uint16_t value);
|
||||
void timer_silence_reset(
|
||||
void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
void timer_init(
|
||||
void);
|
||||
bool timer_silence_elapsed(
|
||||
uint16_t value);
|
||||
void timer_silence_reset(
|
||||
void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
|
||||
@@ -170,7 +170,7 @@ static void snap_received_packet(
|
||||
{
|
||||
uint16_t mtu_len = 0; /* number of octets of packet saved in file */
|
||||
unsigned i = 0; /* counter */
|
||||
static uint8_t mtu[1500] = { 0 };
|
||||
static uint8_t mtu[1500] = { 0 };
|
||||
uint16_t max_data = 0;
|
||||
|
||||
mtu[0] = 0;
|
||||
@@ -204,8 +204,8 @@ static void snap_received_packet(
|
||||
mtu[29] = LO_BYTE(mstp_port->DataLength);
|
||||
mtu[30] = mstp_port->HeaderCRCActual;
|
||||
mtu_len = 31;
|
||||
if (mstp_port->DataLength) {
|
||||
max_data = min(mstp_port->InputBufferSize,mstp_port->DataLength);
|
||||
if (mstp_port->DataLength) {
|
||||
max_data = min(mstp_port->InputBufferSize, mstp_port->DataLength);
|
||||
for (i = 0; i < max_data; i++) {
|
||||
mtu[31 + i] = mstp_port->InputBuffer[i];
|
||||
}
|
||||
|
||||
@@ -217,8 +217,8 @@ static void write_received_packet(
|
||||
fwrite(header, sizeof(header), 1, pFile);
|
||||
if (mstp_port->DataLength) {
|
||||
fwrite(mstp_port->InputBuffer, max_data, 1, pFile);
|
||||
fwrite((char *)&(mstp_port->DataCRCActualMSB), 1, 1, pFile);
|
||||
fwrite((char *)&(mstp_port->DataCRCActualLSB), 1, 1, pFile);
|
||||
fwrite((char *) &(mstp_port->DataCRCActualMSB), 1, 1, pFile);
|
||||
fwrite((char *) &(mstp_port->DataCRCActualLSB), 1, 1, pFile);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "rx_fsm: failed to open %s: %s\n", Capture_Filename,
|
||||
|
||||
@@ -381,7 +381,7 @@ bool bip_init(
|
||||
bip_set_socket(-1);
|
||||
return false;
|
||||
}
|
||||
/* Enables transmission and receipt of broadcast messages on the socket.*/
|
||||
/* Enables transmission and receipt of broadcast messages on the socket. */
|
||||
rv = setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, (char *) &value,
|
||||
sizeof(value));
|
||||
if (rv < 0) {
|
||||
|
||||
@@ -294,14 +294,13 @@ static void Init_DataLink(
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(
|
||||
int argc,
|
||||
char *argv[])
|
||||
{
|
||||
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||
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;
|
||||
BACNET_ADDRESS my_address,
|
||||
broadcast_address;
|
||||
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
@@ -245,7 +245,7 @@ static void write_received_packet(
|
||||
fwrite(&ts_sec, sizeof(ts_sec), 1, pFile);
|
||||
fwrite(&ts_usec, sizeof(ts_usec), 1, pFile);
|
||||
if (mstp_port->DataLength) {
|
||||
max_data = min(mstp_port->InputBufferSize,mstp_port->DataLength);
|
||||
max_data = min(mstp_port->InputBufferSize, mstp_port->DataLength);
|
||||
incl_len = orig_len = 8 + max_data + 2;
|
||||
} else {
|
||||
incl_len = orig_len = 8;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef _STDBOOL_H
|
||||
#define _STDBOOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* C99 Boolean types for compilers without C99 support */
|
||||
/* http://www.opengroup.org/onlinepubs/009695399/basedefs/stdbool.h.html */
|
||||
@@ -14,7 +14,7 @@
|
||||
the values 0 and 1. */
|
||||
/* We choose 8 bit to match C++ */
|
||||
/* It must also promote to integer */
|
||||
typedef int8_t _Bool;
|
||||
typedef int8_t _Bool;
|
||||
#endif
|
||||
|
||||
/* ISO C Standard: 7.16 Boolean type */
|
||||
|
||||
@@ -95,7 +95,7 @@ int arf_decode_service_request(
|
||||
int tag_len = 0;
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value_type = 0;
|
||||
uint16_t type = 0; /* for decoding */
|
||||
uint16_t type = 0; /* for decoding */
|
||||
|
||||
/* check for value pointers */
|
||||
if (apdu_len && data) {
|
||||
|
||||
@@ -100,7 +100,7 @@ int awf_decode_service_request(
|
||||
uint32_t len_value_type = 0;
|
||||
int32_t signed_value = 0;
|
||||
uint32_t unsigned_value = 0;
|
||||
uint16_t type = 0; /* for decoding */
|
||||
uint16_t type = 0; /* for decoding */
|
||||
|
||||
/* check for value pointers */
|
||||
if (apdu_len && data) {
|
||||
|
||||
+417
-439
File diff suppressed because it is too large
Load Diff
+235
-243
@@ -1,243 +1,235 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "bacdcode.h"
|
||||
#include "npdu.h"
|
||||
#include "device.h"
|
||||
#include "datalink.h"
|
||||
#include "timestamp.h"
|
||||
#include "bacdevobjpropref.h"
|
||||
|
||||
int bacapp_encode_context_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
len = bacapp_encode_device_obj_property_ref(&apdu[apdu_len], value);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_encode_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
|
||||
len = encode_context_object_id(&apdu[apdu_len], 0,
|
||||
value->objectIdentifier.type,
|
||||
value->objectIdentifier.instance);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_context_enumerated(&apdu[apdu_len], 1,
|
||||
value->propertyIdentifier);
|
||||
apdu_len += len;
|
||||
|
||||
if ( value->arrayIndex > 0 )
|
||||
{
|
||||
len = encode_context_unsigned(&apdu[apdu_len], 2,
|
||||
value->arrayIndex);
|
||||
apdu_len += len;
|
||||
}
|
||||
len = encode_context_object_id(&apdu[apdu_len], 3,
|
||||
value->deviceIndentifier.type,
|
||||
value->deviceIndentifier.instance);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
|
||||
if ( -1 == ( len = decode_context_object_id(&apdu[apdu_len], 0,
|
||||
&value->objectIdentifier.type,
|
||||
&value->objectIdentifier.instance)) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
if ( -1 == ( len = decode_context_enumerated(&apdu[apdu_len], 1,
|
||||
&value->propertyIdentifier)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
if ( decode_is_context_tag(&apdu[apdu_len], 2 ))
|
||||
{
|
||||
if ( -1 == ( len = decode_context_unsigned(&apdu[apdu_len], 2,
|
||||
&value->arrayIndex)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
value->arrayIndex = 0;
|
||||
}
|
||||
|
||||
if ( decode_is_context_tag(&apdu[apdu_len], 3 ))
|
||||
{
|
||||
if ( -1 == ( len = decode_context_object_id(&apdu[apdu_len], 3,
|
||||
&value->deviceIndentifier.type,
|
||||
&value->deviceIndentifier.instance)) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
value->deviceIndentifier.instance = 0;
|
||||
value->deviceIndentifier.type = 0;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_length;
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
section_length = bacapp_decode_device_obj_property_ref(
|
||||
&apdu[len], value);
|
||||
|
||||
if ( section_length == -1 )
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len += section_length;
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
void testDevIdPropRef(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE inData;
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE outData;
|
||||
uint8_t buffer[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
|
||||
inData.objectIdentifier.instance = 0x1234;
|
||||
inData.objectIdentifier.type = 15;
|
||||
|
||||
inData.propertyIdentifier = 25;
|
||||
|
||||
inData.arrayIndex = 0x5678;
|
||||
|
||||
inData.deviceIndentifier.instance = 0x4343;
|
||||
inData.deviceIndentifier.type = 28;
|
||||
|
||||
inLen = bacapp_encode_device_obj_property_ref(buffer, &inData);
|
||||
outLen = bacapp_decode_device_obj_property_ref(buffer, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
|
||||
ct_test(pTest, inData.objectIdentifier.instance == outData.objectIdentifier.instance);
|
||||
ct_test(pTest, inData.objectIdentifier.type == outData.objectIdentifier.type);
|
||||
|
||||
ct_test(pTest, inData.propertyIdentifier == outData.propertyIdentifier);
|
||||
|
||||
ct_test(pTest, inData.arrayIndex == outData.arrayIndex);
|
||||
|
||||
ct_test(pTest, inData.deviceIndentifier.instance == outData.deviceIndentifier.instance);
|
||||
ct_test(pTest, inData.deviceIndentifier.type == outData.deviceIndentifier.type);
|
||||
}
|
||||
#ifdef TEST_DEV_ID_PROP_REF
|
||||
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Prop Ref", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testDevIdPropRef);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // TEST_DEV_ID_PROP_REF
|
||||
#endif // TEST
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "bacdcode.h"
|
||||
#include "npdu.h"
|
||||
#include "device.h"
|
||||
#include "datalink.h"
|
||||
#include "timestamp.h"
|
||||
#include "bacdevobjpropref.h"
|
||||
|
||||
int bacapp_encode_context_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
len = bacapp_encode_device_obj_property_ref(&apdu[apdu_len], value);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_encode_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
|
||||
len =
|
||||
encode_context_object_id(&apdu[apdu_len], 0,
|
||||
value->objectIdentifier.type, value->objectIdentifier.instance);
|
||||
apdu_len += len;
|
||||
|
||||
len =
|
||||
encode_context_enumerated(&apdu[apdu_len], 1,
|
||||
value->propertyIdentifier);
|
||||
apdu_len += len;
|
||||
|
||||
if (value->arrayIndex > 0) {
|
||||
len = encode_context_unsigned(&apdu[apdu_len], 2, value->arrayIndex);
|
||||
apdu_len += len;
|
||||
}
|
||||
len =
|
||||
encode_context_object_id(&apdu[apdu_len], 3,
|
||||
value->deviceIndentifier.type, value->deviceIndentifier.instance);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
|
||||
if (-1 == (len =
|
||||
decode_context_object_id(&apdu[apdu_len], 0,
|
||||
&value->objectIdentifier.type,
|
||||
&value->objectIdentifier.instance))) {
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
if (-1 == (len =
|
||||
decode_context_enumerated(&apdu[apdu_len], 1,
|
||||
&value->propertyIdentifier))) {
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
if (decode_is_context_tag(&apdu[apdu_len], 2)) {
|
||||
if (-1 == (len =
|
||||
decode_context_unsigned(&apdu[apdu_len], 2,
|
||||
&value->arrayIndex))) {
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
} else {
|
||||
value->arrayIndex = 0;
|
||||
}
|
||||
|
||||
if (decode_is_context_tag(&apdu[apdu_len], 3)) {
|
||||
if (-1 == (len =
|
||||
decode_context_object_id(&apdu[apdu_len], 3,
|
||||
&value->deviceIndentifier.type,
|
||||
&value->deviceIndentifier.instance))) {
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
} else {
|
||||
value->deviceIndentifier.instance = 0;
|
||||
value->deviceIndentifier.type = 0;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_device_obj_property_ref(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_length;
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
section_length =
|
||||
bacapp_decode_device_obj_property_ref(&apdu[len], value);
|
||||
|
||||
if (section_length == -1) {
|
||||
len = -1;
|
||||
} else {
|
||||
len += section_length;
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
} else {
|
||||
len = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
void testDevIdPropRef(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE inData;
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE outData;
|
||||
uint8_t buffer[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
|
||||
inData.objectIdentifier.instance = 0x1234;
|
||||
inData.objectIdentifier.type = 15;
|
||||
|
||||
inData.propertyIdentifier = 25;
|
||||
|
||||
inData.arrayIndex = 0x5678;
|
||||
|
||||
inData.deviceIndentifier.instance = 0x4343;
|
||||
inData.deviceIndentifier.type = 28;
|
||||
|
||||
inLen = bacapp_encode_device_obj_property_ref(buffer, &inData);
|
||||
outLen = bacapp_decode_device_obj_property_ref(buffer, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
|
||||
ct_test(pTest,
|
||||
inData.objectIdentifier.instance == outData.objectIdentifier.instance);
|
||||
ct_test(pTest,
|
||||
inData.objectIdentifier.type == outData.objectIdentifier.type);
|
||||
|
||||
ct_test(pTest, inData.propertyIdentifier == outData.propertyIdentifier);
|
||||
|
||||
ct_test(pTest, inData.arrayIndex == outData.arrayIndex);
|
||||
|
||||
ct_test(pTest,
|
||||
inData.deviceIndentifier.instance ==
|
||||
outData.deviceIndentifier.instance);
|
||||
ct_test(pTest,
|
||||
inData.deviceIndentifier.type == outData.deviceIndentifier.type);
|
||||
}
|
||||
|
||||
#ifdef TEST_DEV_ID_PROP_REF
|
||||
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Prop Ref", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testDevIdPropRef);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // TEST_DEV_ID_PROP_REF
|
||||
#endif // TEST
|
||||
|
||||
+432
-403
@@ -1,403 +1,432 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "bacdcode.h"
|
||||
#include "npdu.h"
|
||||
#include "device.h"
|
||||
#include "datalink.h"
|
||||
#include "timestamp.h"
|
||||
#include "bacpropstates.h"
|
||||
|
||||
int bacapp_decode_property_state(
|
||||
uint8_t * apdu,
|
||||
BACNET_PROPERTY_STATE * value)
|
||||
{
|
||||
int len = 0;
|
||||
uint32_t len_value_type;
|
||||
int section_length;
|
||||
|
||||
|
||||
section_length =
|
||||
decode_tag_number_and_value(&apdu[len], (uint8_t*)&value->tag,
|
||||
&len_value_type);
|
||||
|
||||
if ( -1 == section_length )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
len += section_length;
|
||||
switch(value->tag)
|
||||
{
|
||||
case BOOLEAN_VALUE:
|
||||
value->state.booleanValue = decode_boolean(len_value_type);
|
||||
break;
|
||||
|
||||
case BINARY_VALUE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.binaryValue)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_TYPE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.eventType)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case POLARITY:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.polarity)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROGRAM_CHANGE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.programChange)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROGRAM_STATE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.programState)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case REASON_FOR_HALT:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.programError)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case RELIABILITY:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.reliability)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.state)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SYSTEM_STATUS:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.systemStatus)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNITS:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.units)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNSIGNED_VALUE:
|
||||
if ( -1 == ( section_length = decode_unsigned(&apdu[len], len_value_type, &value->state.unsignedValue)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LIFE_SAFETY_MODE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.lifeSafetyMode)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LIFE_SAFETY_STATE:
|
||||
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.lifeSafetyState)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
len += section_length;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_property_state(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_PROPERTY_STATE * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_length;
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
section_length = bacapp_decode_property_state(
|
||||
&apdu[len], value);
|
||||
|
||||
if ( section_length == -1 )
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len += section_length;
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int bacapp_encode_property_state(
|
||||
uint8_t * apdu,
|
||||
BACNET_PROPERTY_STATE * value)
|
||||
{
|
||||
int len = 0; /* length of each encoding */
|
||||
if (value && apdu) {
|
||||
switch(value->tag)
|
||||
{
|
||||
case BOOLEAN_VALUE:
|
||||
len = encode_context_boolean(&apdu[0], 0, value->state.booleanValue);
|
||||
break;
|
||||
|
||||
case BINARY_VALUE:
|
||||
len = encode_context_enumerated(&apdu[0], 1, value->state.binaryValue);
|
||||
break;
|
||||
|
||||
case EVENT_TYPE:
|
||||
len = encode_context_enumerated(&apdu[0], 2, value->state.eventType);
|
||||
break;
|
||||
|
||||
case POLARITY:
|
||||
len = encode_context_enumerated(&apdu[0], 3, value->state.polarity);
|
||||
break;
|
||||
|
||||
case PROGRAM_CHANGE:
|
||||
len = encode_context_enumerated(&apdu[0], 4, value->state.programChange);
|
||||
break;
|
||||
|
||||
case PROGRAM_STATE:
|
||||
len = encode_context_enumerated(&apdu[0], 5, value->state.programState);
|
||||
break;
|
||||
|
||||
case REASON_FOR_HALT:
|
||||
len = encode_context_enumerated(&apdu[0], 6, value->state.programError);
|
||||
break;
|
||||
|
||||
case RELIABILITY:
|
||||
len = encode_context_enumerated(&apdu[0], 7, value->state.reliability);
|
||||
break;
|
||||
|
||||
case STATE:
|
||||
len = encode_context_enumerated(&apdu[0], 8, value->state.state);
|
||||
break;
|
||||
|
||||
case SYSTEM_STATUS:
|
||||
len = encode_context_enumerated(&apdu[0], 9, value->state.systemStatus);
|
||||
break;
|
||||
|
||||
case UNITS:
|
||||
len = encode_context_enumerated(&apdu[0], 10, value->state.units);
|
||||
break;
|
||||
|
||||
case UNSIGNED_VALUE:
|
||||
len = encode_context_unsigned(&apdu[0], 11, value->state.unsignedValue);
|
||||
break;
|
||||
|
||||
case LIFE_SAFETY_MODE:
|
||||
len = encode_context_enumerated(&apdu[0], 12, value->state.lifeSafetyMode);
|
||||
break;
|
||||
|
||||
case LIFE_SAFETY_STATE:
|
||||
len = encode_context_enumerated(&apdu[0], 13, value->state.lifeSafetyState);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
void testPropStates(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_PROPERTY_STATE inData;
|
||||
BACNET_PROPERTY_STATE outData;
|
||||
uint8_t appMsg[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
inData.tag = BOOLEAN_VALUE;
|
||||
inData.state.booleanValue = true;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag );
|
||||
ct_test(pTest, inData.state.booleanValue == outData.state.booleanValue );
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = BINARY_VALUE;
|
||||
inData.state.binaryValue = BINARY_ACTIVE;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag );
|
||||
ct_test(pTest, inData.state.binaryValue == outData.state.binaryValue );
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = EVENT_TYPE;
|
||||
inData.state.eventType = EVENT_BUFFER_READY;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag );
|
||||
ct_test(pTest, inData.state.eventType == outData.state.eventType );
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = POLARITY;
|
||||
inData.state.polarity = POLARITY_REVERSE;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag );
|
||||
ct_test(pTest, inData.state.polarity == outData.state.polarity );
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = PROGRAM_CHANGE;
|
||||
inData.state.programChange = PROGRAM_REQUEST_RESTART;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag );
|
||||
ct_test(pTest, inData.state.programChange == outData.state.programChange );
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = UNSIGNED_VALUE;
|
||||
inData.state.unsignedValue = 0xdeadbeef;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag );
|
||||
ct_test(pTest, inData.state.unsignedValue == outData.state.unsignedValue );
|
||||
|
||||
}
|
||||
|
||||
#ifdef TEST_PROP_STATES
|
||||
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Event", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testPropStates);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // TEST_PROP_STATES
|
||||
#endif // TEST
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "bacdcode.h"
|
||||
#include "npdu.h"
|
||||
#include "device.h"
|
||||
#include "datalink.h"
|
||||
#include "timestamp.h"
|
||||
#include "bacpropstates.h"
|
||||
|
||||
int bacapp_decode_property_state(
|
||||
uint8_t * apdu,
|
||||
BACNET_PROPERTY_STATE * value)
|
||||
{
|
||||
int len = 0;
|
||||
uint32_t len_value_type;
|
||||
int section_length;
|
||||
|
||||
|
||||
section_length =
|
||||
decode_tag_number_and_value(&apdu[len], (uint8_t *) & value->tag,
|
||||
&len_value_type);
|
||||
|
||||
if (-1 == section_length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
len += section_length;
|
||||
switch (value->tag) {
|
||||
case BOOLEAN_VALUE:
|
||||
value->state.booleanValue = decode_boolean(len_value_type);
|
||||
break;
|
||||
|
||||
case BINARY_VALUE:
|
||||
if (-1 == (section_length =
|
||||
decode_enumerated(&apdu[len], len_value_type,
|
||||
&value->state.binaryValue))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_TYPE:
|
||||
if (-1 == (section_length =
|
||||
decode_enumerated(&apdu[len], len_value_type,
|
||||
&value->state.eventType))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case POLARITY:
|
||||
if (-1 == (section_length =
|
||||
decode_enumerated(&apdu[len], len_value_type,
|
||||
&value->state.polarity))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROGRAM_CHANGE:
|
||||
if (-1 == (section_length =
|
||||
decode_enumerated(&apdu[len], len_value_type,
|
||||
&value->state.programChange))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case PROGRAM_STATE:
|
||||
if (-1 == (section_length =
|
||||
decode_enumerated(&apdu[len], len_value_type,
|
||||
&value->state.programState))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case REASON_FOR_HALT:
|
||||
if (-1 == (section_length =
|
||||
decode_enumerated(&apdu[len], len_value_type,
|
||||
&value->state.programError))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case RELIABILITY:
|
||||
if (-1 == (section_length =
|
||||
decode_enumerated(&apdu[len], len_value_type,
|
||||
&value->state.reliability))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE:
|
||||
if (-1 == (section_length =
|
||||
decode_enumerated(&apdu[len], len_value_type,
|
||||
&value->state.state))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case SYSTEM_STATUS:
|
||||
if (-1 == (section_length =
|
||||
decode_enumerated(&apdu[len], len_value_type,
|
||||
&value->state.systemStatus))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNITS:
|
||||
if (-1 == (section_length =
|
||||
decode_enumerated(&apdu[len], len_value_type,
|
||||
&value->state.units))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case UNSIGNED_VALUE:
|
||||
if (-1 == (section_length =
|
||||
decode_unsigned(&apdu[len], len_value_type,
|
||||
&value->state.unsignedValue))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LIFE_SAFETY_MODE:
|
||||
if (-1 == (section_length =
|
||||
decode_enumerated(&apdu[len], len_value_type,
|
||||
&value->state.lifeSafetyMode))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case LIFE_SAFETY_STATE:
|
||||
if (-1 == (section_length =
|
||||
decode_enumerated(&apdu[len], len_value_type,
|
||||
&value->state.lifeSafetyState))) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
len += section_length;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_property_state(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_PROPERTY_STATE * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_length;
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
section_length = bacapp_decode_property_state(&apdu[len], value);
|
||||
|
||||
if (section_length == -1) {
|
||||
len = -1;
|
||||
} else {
|
||||
len += section_length;
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
} else {
|
||||
len = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int bacapp_encode_property_state(
|
||||
uint8_t * apdu,
|
||||
BACNET_PROPERTY_STATE * value)
|
||||
{
|
||||
int len = 0; /* length of each encoding */
|
||||
if (value && apdu) {
|
||||
switch (value->tag) {
|
||||
case BOOLEAN_VALUE:
|
||||
len =
|
||||
encode_context_boolean(&apdu[0], 0,
|
||||
value->state.booleanValue);
|
||||
break;
|
||||
|
||||
case BINARY_VALUE:
|
||||
len =
|
||||
encode_context_enumerated(&apdu[0], 1,
|
||||
value->state.binaryValue);
|
||||
break;
|
||||
|
||||
case EVENT_TYPE:
|
||||
len =
|
||||
encode_context_enumerated(&apdu[0], 2,
|
||||
value->state.eventType);
|
||||
break;
|
||||
|
||||
case POLARITY:
|
||||
len =
|
||||
encode_context_enumerated(&apdu[0], 3,
|
||||
value->state.polarity);
|
||||
break;
|
||||
|
||||
case PROGRAM_CHANGE:
|
||||
len =
|
||||
encode_context_enumerated(&apdu[0], 4,
|
||||
value->state.programChange);
|
||||
break;
|
||||
|
||||
case PROGRAM_STATE:
|
||||
len =
|
||||
encode_context_enumerated(&apdu[0], 5,
|
||||
value->state.programState);
|
||||
break;
|
||||
|
||||
case REASON_FOR_HALT:
|
||||
len =
|
||||
encode_context_enumerated(&apdu[0], 6,
|
||||
value->state.programError);
|
||||
break;
|
||||
|
||||
case RELIABILITY:
|
||||
len =
|
||||
encode_context_enumerated(&apdu[0], 7,
|
||||
value->state.reliability);
|
||||
break;
|
||||
|
||||
case STATE:
|
||||
len =
|
||||
encode_context_enumerated(&apdu[0], 8, value->state.state);
|
||||
break;
|
||||
|
||||
case SYSTEM_STATUS:
|
||||
len =
|
||||
encode_context_enumerated(&apdu[0], 9,
|
||||
value->state.systemStatus);
|
||||
break;
|
||||
|
||||
case UNITS:
|
||||
len =
|
||||
encode_context_enumerated(&apdu[0], 10,
|
||||
value->state.units);
|
||||
break;
|
||||
|
||||
case UNSIGNED_VALUE:
|
||||
len =
|
||||
encode_context_unsigned(&apdu[0], 11,
|
||||
value->state.unsignedValue);
|
||||
break;
|
||||
|
||||
case LIFE_SAFETY_MODE:
|
||||
len =
|
||||
encode_context_enumerated(&apdu[0], 12,
|
||||
value->state.lifeSafetyMode);
|
||||
break;
|
||||
|
||||
case LIFE_SAFETY_STATE:
|
||||
len =
|
||||
encode_context_enumerated(&apdu[0], 13,
|
||||
value->state.lifeSafetyState);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
void testPropStates(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_PROPERTY_STATE inData;
|
||||
BACNET_PROPERTY_STATE outData;
|
||||
uint8_t appMsg[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
inData.tag = BOOLEAN_VALUE;
|
||||
inData.state.booleanValue = true;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag);
|
||||
ct_test(pTest, inData.state.booleanValue == outData.state.booleanValue);
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = BINARY_VALUE;
|
||||
inData.state.binaryValue = BINARY_ACTIVE;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag);
|
||||
ct_test(pTest, inData.state.binaryValue == outData.state.binaryValue);
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = EVENT_TYPE;
|
||||
inData.state.eventType = EVENT_BUFFER_READY;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag);
|
||||
ct_test(pTest, inData.state.eventType == outData.state.eventType);
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = POLARITY;
|
||||
inData.state.polarity = POLARITY_REVERSE;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag);
|
||||
ct_test(pTest, inData.state.polarity == outData.state.polarity);
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = PROGRAM_CHANGE;
|
||||
inData.state.programChange = PROGRAM_REQUEST_RESTART;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag);
|
||||
ct_test(pTest, inData.state.programChange == outData.state.programChange);
|
||||
|
||||
/****************
|
||||
*****************
|
||||
****************/
|
||||
inData.tag = UNSIGNED_VALUE;
|
||||
inData.state.unsignedValue = 0xdeadbeef;
|
||||
|
||||
inLen = bacapp_encode_property_state(appMsg, &inData);
|
||||
|
||||
memset(&outData, 0, sizeof(outData));
|
||||
|
||||
outLen = bacapp_decode_property_state(appMsg, &outData);
|
||||
|
||||
ct_test(pTest, outLen == inLen);
|
||||
ct_test(pTest, inData.tag == outData.tag);
|
||||
ct_test(pTest, inData.state.unsignedValue == outData.state.unsignedValue);
|
||||
|
||||
}
|
||||
|
||||
#ifdef TEST_PROP_STATES
|
||||
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Event", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testPropStates);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // TEST_PROP_STATES
|
||||
#endif // TEST
|
||||
|
||||
+11
-12
@@ -78,23 +78,22 @@ int decode_real(
|
||||
|
||||
int decode_context_real(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
uint8_t tag_number,
|
||||
float *real_value)
|
||||
{
|
||||
uint32_t len_value;
|
||||
int len = 0;
|
||||
int len = 0;
|
||||
|
||||
if (decode_is_context_tag(&apdu[len], tag_number)) {
|
||||
len += decode_tag_number_and_value(&apdu[len], &tag_number,
|
||||
&len_value);
|
||||
len += decode_real(&apdu[len], real_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
if (decode_is_context_tag(&apdu[len], tag_number)) {
|
||||
len +=
|
||||
decode_tag_number_and_value(&apdu[len], &tag_number, &len_value);
|
||||
len += decode_real(&apdu[len], real_value);
|
||||
} else {
|
||||
len = -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/* from clause 20.2.6 Encoding of a Real Number Value */
|
||||
/* returns the number of apdu bytes consumed */
|
||||
int encode_bacnet_real(
|
||||
|
||||
@@ -99,7 +99,7 @@ uint8_t bitstring_bits_used(
|
||||
uint8_t bitstring_bytes_used(
|
||||
BACNET_BIT_STRING * bit_string)
|
||||
{
|
||||
uint8_t len = 0; /* return value */
|
||||
uint8_t len = 0; /* return value */
|
||||
uint8_t used_bytes = 0;
|
||||
uint8_t last_bit = 0;
|
||||
|
||||
@@ -544,7 +544,7 @@ bool octetstring_value_same(
|
||||
BACNET_OCTET_STRING * octet_string1,
|
||||
BACNET_OCTET_STRING * octet_string2)
|
||||
{
|
||||
size_t i = 0; /* loop counter */
|
||||
size_t i = 0; /* loop counter */
|
||||
|
||||
if (octet_string1 && octet_string2) {
|
||||
if ((octet_string1->length == octet_string2->length) &&
|
||||
|
||||
@@ -174,7 +174,7 @@ int cov_notify_decode_service_request(
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value = 0;
|
||||
uint32_t decoded_value = 0; /* for decoding */
|
||||
uint16_t decoded_type = 0; /* for decoding */
|
||||
uint16_t decoded_type = 0; /* for decoding */
|
||||
int property = 0; /* for decoding */
|
||||
BACNET_PROPERTY_VALUE *value = NULL; /* value in list */
|
||||
|
||||
@@ -373,7 +373,7 @@ int cov_subscribe_decode_service_request(
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value = 0;
|
||||
uint32_t decoded_value = 0; /* for decoding */
|
||||
uint16_t decoded_type = 0; /* for decoding */
|
||||
uint16_t decoded_type = 0; /* for decoding */
|
||||
|
||||
if (apdu_len && data) {
|
||||
/* tag 0 - subscriberProcessIdentifier */
|
||||
@@ -519,7 +519,7 @@ int cov_subscribe_property_decode_service_request(
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value = 0;
|
||||
uint32_t decoded_value = 0; /* for decoding */
|
||||
uint16_t decoded_type = 0; /* for decoding */
|
||||
uint16_t decoded_type = 0; /* for decoding */
|
||||
int property = 0; /* for decoding */
|
||||
|
||||
if (apdu_len && data) {
|
||||
|
||||
+70
-80
@@ -75,7 +75,7 @@ static uint8_t month_days(
|
||||
if ((month == 2) && is_leap_year(year))
|
||||
return 29;
|
||||
else if (month >= 1 && month <= 12)
|
||||
return (uint8_t)month_days[month];
|
||||
return (uint8_t) month_days[month];
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@@ -435,48 +435,47 @@ int bacapp_encode_context_datetime(
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE_TIME * value)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0;
|
||||
int len = 0;
|
||||
int apdu_len = 0;
|
||||
|
||||
|
||||
if ( apdu && value )
|
||||
{
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
if (apdu && value) {
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_application_date(&apdu[apdu_len], &value->date);
|
||||
apdu_len += len;
|
||||
len = encode_application_date(&apdu[apdu_len], &value->date);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_application_time(&apdu[apdu_len], &value->time);
|
||||
apdu_len += len;
|
||||
len = encode_application_time(&apdu[apdu_len], &value->time);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
return apdu_len;
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_datetime(
|
||||
uint8_t * apdu,
|
||||
BACNET_DATE_TIME * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_len;
|
||||
int len = 0;
|
||||
int section_len;
|
||||
|
||||
if ( -1 == ( section_len = decode_application_date(&apdu[len], &value->date) ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
len += section_len;
|
||||
if (-1 == (section_len =
|
||||
decode_application_date(&apdu[len], &value->date))) {
|
||||
return -1;
|
||||
}
|
||||
len += section_len;
|
||||
|
||||
if ( -1 == ( section_len = decode_application_time(&apdu[len], &value->time) ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (-1 == (section_len =
|
||||
decode_application_time(&apdu[len], &value->time))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
len += section_len;
|
||||
|
||||
return len;
|
||||
len += section_len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_datetime(
|
||||
@@ -484,35 +483,27 @@ int bacapp_decode_context_datetime(
|
||||
uint8_t tag_number,
|
||||
BACNET_DATE_TIME * value)
|
||||
{
|
||||
int apdu_len = 0;
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
int len;
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[apdu_len], tag_number)) {
|
||||
apdu_len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (decode_is_opening_tag_number(&apdu[apdu_len], tag_number)) {
|
||||
apdu_len++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( -1 == (len = bacapp_decode_datetime(&apdu[apdu_len], value)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
apdu_len += len;
|
||||
}
|
||||
if (-1 == (len = bacapp_decode_datetime(&apdu[apdu_len], value))) {
|
||||
return -1;
|
||||
} else {
|
||||
apdu_len += len;
|
||||
}
|
||||
|
||||
if (decode_is_closing_tag_number(&apdu[apdu_len], tag_number))
|
||||
{
|
||||
apdu_len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return apdu_len;
|
||||
if (decode_is_closing_tag_number(&apdu[apdu_len], tag_number)) {
|
||||
apdu_len++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
|
||||
@@ -836,36 +827,36 @@ void testBACnetDayOfWeek(
|
||||
void testDatetimeCodec(
|
||||
Test * pTest)
|
||||
{
|
||||
uint8_t apdu[MAX_APDU];
|
||||
BACNET_DATE_TIME datetimeIn;
|
||||
BACNET_DATE_TIME datetimeOut;
|
||||
int inLen;
|
||||
int outLen;
|
||||
uint8_t apdu[MAX_APDU];
|
||||
BACNET_DATE_TIME datetimeIn;
|
||||
BACNET_DATE_TIME datetimeOut;
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
datetimeIn.date.day = 1;
|
||||
datetimeIn.date.month = 2;
|
||||
datetimeIn.date.wday = 3;
|
||||
datetimeIn.date.year = 1904;
|
||||
datetimeIn.date.day = 1;
|
||||
datetimeIn.date.month = 2;
|
||||
datetimeIn.date.wday = 3;
|
||||
datetimeIn.date.year = 1904;
|
||||
|
||||
datetimeIn.time.hour = 5;
|
||||
datetimeIn.time.min = 6;
|
||||
datetimeIn.time.sec = 7;
|
||||
datetimeIn.time.hundredths = 8;
|
||||
datetimeIn.time.hour = 5;
|
||||
datetimeIn.time.min = 6;
|
||||
datetimeIn.time.sec = 7;
|
||||
datetimeIn.time.hundredths = 8;
|
||||
|
||||
inLen = bacapp_encode_context_datetime(apdu, 10, &datetimeIn);
|
||||
outLen = bacapp_decode_context_datetime(apdu, 10, &datetimeOut);
|
||||
inLen = bacapp_encode_context_datetime(apdu, 10, &datetimeIn);
|
||||
outLen = bacapp_decode_context_datetime(apdu, 10, &datetimeOut);
|
||||
|
||||
ct_test(pTest, inLen == outLen );
|
||||
ct_test(pTest, inLen == outLen);
|
||||
|
||||
ct_test(pTest, datetimeIn.date.day == datetimeOut.date.day);
|
||||
ct_test(pTest, datetimeIn.date.month == datetimeOut.date.month);
|
||||
ct_test(pTest, datetimeIn.date.wday == datetimeOut.date.wday);
|
||||
ct_test(pTest, datetimeIn.date.year == datetimeOut.date.year);
|
||||
ct_test(pTest, datetimeIn.date.day == datetimeOut.date.day);
|
||||
ct_test(pTest, datetimeIn.date.month == datetimeOut.date.month);
|
||||
ct_test(pTest, datetimeIn.date.wday == datetimeOut.date.wday);
|
||||
ct_test(pTest, datetimeIn.date.year == datetimeOut.date.year);
|
||||
|
||||
ct_test(pTest, datetimeIn.time.hour == datetimeOut.time.hour);
|
||||
ct_test(pTest, datetimeIn.time.min == datetimeOut.time.min);
|
||||
ct_test(pTest, datetimeIn.time.sec == datetimeOut.time.sec);
|
||||
ct_test(pTest, datetimeIn.time.hundredths == datetimeOut.time.hundredths);
|
||||
ct_test(pTest, datetimeIn.time.hour == datetimeOut.time.hour);
|
||||
ct_test(pTest, datetimeIn.time.min == datetimeOut.time.min);
|
||||
ct_test(pTest, datetimeIn.time.sec == datetimeOut.time.sec);
|
||||
ct_test(pTest, datetimeIn.time.hundredths == datetimeOut.time.hundredths);
|
||||
|
||||
}
|
||||
|
||||
@@ -909,4 +900,3 @@ int main(
|
||||
|
||||
#endif /* TEST_DATE_TIME */
|
||||
#endif /* TEST */
|
||||
|
||||
|
||||
+1534
-1387
File diff suppressed because it is too large
Load Diff
@@ -37,7 +37,7 @@
|
||||
char *filename_remove_path(
|
||||
const char *filename_in)
|
||||
{
|
||||
char *filename_out = (char *)filename_in;
|
||||
char *filename_out = (char *) filename_in;
|
||||
|
||||
/* allow the device ID to be set */
|
||||
if (filename_in) {
|
||||
|
||||
@@ -80,7 +80,7 @@ int iam_decode_service_request(
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
uint16_t object_type = 0; /* should be a Device Object */
|
||||
uint16_t object_type = 0; /* should be a Device Object */
|
||||
uint32_t object_instance = 0;
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value = 0;
|
||||
|
||||
@@ -77,7 +77,7 @@ int ihave_decode_service_request(
|
||||
int len = 0;
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value = 0;
|
||||
uint16_t decoded_type = 0; /* for decoding */
|
||||
uint16_t decoded_type = 0; /* for decoding */
|
||||
|
||||
if (apdu_len && data) {
|
||||
/* deviceIdentifier */
|
||||
|
||||
+10
-11
@@ -36,12 +36,12 @@
|
||||
/* copy len bytes from src to offset of dest if there is enough space. */
|
||||
/* returns 0 if there is not enough space, or the number of bytes copied. */
|
||||
size_t memcopy(
|
||||
void * dest,
|
||||
void * src,
|
||||
size_t offset, /* where in dest to put the data */
|
||||
void *dest,
|
||||
void *src,
|
||||
size_t offset, /* where in dest to put the data */
|
||||
size_t len, /* amount of data to copy */
|
||||
size_t max) /* total size of destination */
|
||||
{
|
||||
size_t max)
|
||||
{ /* total size of destination */
|
||||
size_t i;
|
||||
size_t copy_len = 0;
|
||||
char *s1, *s2;
|
||||
@@ -73,15 +73,14 @@ void test_memcopy(
|
||||
char big_buffer[480] = "";
|
||||
size_t len = 0;
|
||||
|
||||
len = memcopy(&buffer[0], &data1[0], 0,
|
||||
sizeof(data1), sizeof(buffer));
|
||||
len = memcopy(&buffer[0], &data1[0], 0, sizeof(data1), sizeof(buffer));
|
||||
ct_test(pTest, len == sizeof(data1));
|
||||
ct_test(pTest, memcmp(&buffer[0], &data1[0], len) == 0);
|
||||
len = memcopy(&buffer[0], &data2[0], len,
|
||||
sizeof(data2), sizeof(buffer));
|
||||
len = memcopy(&buffer[0], &data2[0], len, sizeof(data2), sizeof(buffer));
|
||||
ct_test(pTest, len == sizeof(data2));
|
||||
len = memcopy(&buffer[0], &big_buffer[0], 1,
|
||||
sizeof(big_buffer), sizeof(buffer));
|
||||
len =
|
||||
memcopy(&buffer[0], &big_buffer[0], 1, sizeof(big_buffer),
|
||||
sizeof(buffer));
|
||||
ct_test(pTest, len == 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ int rp_decode_service_request(
|
||||
unsigned len = 0;
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value_type = 0;
|
||||
uint16_t type = 0; /* for decoding */
|
||||
uint16_t type = 0; /* for decoding */
|
||||
int property = 0; /* for decoding */
|
||||
uint32_t array_value = 0; /* for decoding */
|
||||
|
||||
@@ -214,8 +214,8 @@ int rp_ack_decode_service_request(
|
||||
uint32_t len_value_type = 0;
|
||||
int tag_len = 0; /* length of tag decode */
|
||||
int len = 0; /* total length of decodes */
|
||||
uint16_t object = 0; /* object type */
|
||||
int property = 0; /* for decoding */
|
||||
uint16_t object = 0; /* object type */
|
||||
int property = 0; /* for decoding */
|
||||
uint32_t array_value = 0; /* for decoding */
|
||||
|
||||
/* FIXME: check apdu_len against the len during decode */
|
||||
|
||||
+16
-13
@@ -110,13 +110,13 @@ int rpm_encode_apdu(
|
||||
uint8_t * apdu,
|
||||
size_t max_apdu,
|
||||
uint8_t invoke_id,
|
||||
BACNET_READ_ACCESS_DATA *read_access_data)
|
||||
BACNET_READ_ACCESS_DATA * read_access_data)
|
||||
{
|
||||
int apdu_len = 0; /* total length of the apdu, return value */
|
||||
int len = 0; /* length of the data */
|
||||
BACNET_READ_ACCESS_DATA *rpm_object; /* current object */
|
||||
uint8_t apdu_temp[16]; /* temp for data before copy */
|
||||
BACNET_PROPERTY_REFERENCE *rpm_property; /* current property */
|
||||
int len = 0; /* length of the data */
|
||||
BACNET_READ_ACCESS_DATA *rpm_object; /* current object */
|
||||
uint8_t apdu_temp[16]; /* temp for data before copy */
|
||||
BACNET_PROPERTY_REFERENCE *rpm_property; /* current property */
|
||||
|
||||
len = rpm_encode_apdu_init(&apdu_temp[0], invoke_id);
|
||||
len = memcopy(&apdu[0], &apdu_temp[0], apdu_len, len, max_apdu);
|
||||
@@ -126,9 +126,9 @@ int rpm_encode_apdu(
|
||||
apdu_len += len;
|
||||
rpm_object = read_access_data;
|
||||
while (rpm_object) {
|
||||
len = encode_context_object_id(&apdu_temp[0], 0,
|
||||
rpm_object->object_type,
|
||||
rpm_object->object_instance);
|
||||
len =
|
||||
encode_context_object_id(&apdu_temp[0], 0, rpm_object->object_type,
|
||||
rpm_object->object_instance);
|
||||
len = memcopy(&apdu[0], &apdu_temp[0], apdu_len, len, max_apdu);
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
@@ -144,7 +144,8 @@ int rpm_encode_apdu(
|
||||
rpm_property = rpm_object->listOfProperties;
|
||||
while (rpm_property) {
|
||||
/* stuff as many properties into it as APDU length will allow */
|
||||
len = encode_context_enumerated(&apdu_temp[0], 0,
|
||||
len =
|
||||
encode_context_enumerated(&apdu_temp[0], 0,
|
||||
rpm_property->propertyIdentifier);
|
||||
len = memcopy(&apdu[0], &apdu_temp[0], apdu_len, len, max_apdu);
|
||||
if (len == 0) {
|
||||
@@ -153,9 +154,11 @@ int rpm_encode_apdu(
|
||||
apdu_len += len;
|
||||
/* optional array index */
|
||||
if (rpm_property->propertyArrayIndex != BACNET_ARRAY_ALL) {
|
||||
len = encode_context_unsigned(&apdu_temp[0], 1,
|
||||
len =
|
||||
encode_context_unsigned(&apdu_temp[0], 1,
|
||||
rpm_property->propertyArrayIndex);
|
||||
len = memcopy(&apdu[0], &apdu_temp[0], apdu_len, len, max_apdu);
|
||||
len =
|
||||
memcopy(&apdu[0], &apdu_temp[0], apdu_len, len, max_apdu);
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -183,7 +186,7 @@ int rpm_decode_object_id(
|
||||
uint32_t * object_instance)
|
||||
{
|
||||
unsigned len = 0;
|
||||
uint16_t type = 0; /* for decoding */
|
||||
uint16_t type = 0; /* for decoding */
|
||||
|
||||
/* check for value pointers */
|
||||
if (apdu && apdu_len && object_type && object_instance) {
|
||||
@@ -383,7 +386,7 @@ int rpm_ack_decode_object_id(
|
||||
uint32_t * object_instance)
|
||||
{
|
||||
unsigned len = 0;
|
||||
uint16_t type = 0; /* for decoding */
|
||||
uint16_t type = 0; /* for decoding */
|
||||
|
||||
/* check for value pointers */
|
||||
if (apdu && apdu_len && object_type && object_instance) {
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
void sbuf_init(
|
||||
STATIC_BUFFER * b, /* static buffer structure */
|
||||
char *data, /* data block */
|
||||
unsigned size) /* actual size, in bytes, of the data block or array of data */
|
||||
{
|
||||
unsigned size)
|
||||
{ /* actual size, in bytes, of the data block or array of data */
|
||||
if (b) {
|
||||
b->data = data;
|
||||
b->size = size;
|
||||
|
||||
+301
-283
@@ -1,283 +1,301 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#include "assert.h"
|
||||
#include "timestamp.h"
|
||||
|
||||
int bacapp_encode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value)
|
||||
{
|
||||
int len = 0; /* length of each encoding */
|
||||
int apdu_len = 0;
|
||||
|
||||
if (value && apdu) {
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
switch(value->tag)
|
||||
{
|
||||
case TIME_STAMP_TIME:
|
||||
len = encode_context_time(&apdu[apdu_len], 0, &value->value.time);
|
||||
break;
|
||||
|
||||
case TIME_STAMP_SEQUENCE:
|
||||
len = encode_context_unsigned(&apdu[apdu_len], 1, value->value.sequenceNum);
|
||||
break;
|
||||
|
||||
case TIME_STAMP_DATETIME:
|
||||
len = bacapp_encode_context_datetime(&apdu[apdu_len], 2, &value->value.dateTime);
|
||||
break;
|
||||
|
||||
default:
|
||||
len = 0;
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_len;
|
||||
uint32_t len_value_type;
|
||||
uint32_t sequenceNum;
|
||||
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
|
||||
section_len =
|
||||
decode_tag_number_and_value(&apdu[len], &value->tag,
|
||||
&len_value_type);
|
||||
|
||||
if ( -1 == section_len )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
switch( value->tag )
|
||||
{
|
||||
case TIME_STAMP_TIME:
|
||||
if ( (section_len = decode_context_bacnet_time(&apdu[len], TIME_STAMP_TIME, &value->value.time)) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len += section_len;
|
||||
}
|
||||
break;
|
||||
|
||||
case TIME_STAMP_SEQUENCE:
|
||||
if ( (section_len = decode_context_unsigned(&apdu[len], TIME_STAMP_SEQUENCE, &sequenceNum)) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( sequenceNum <= 0xffff )
|
||||
{
|
||||
len += section_len;
|
||||
value->value.sequenceNum = (uint16_t)sequenceNum;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TIME_STAMP_DATETIME:
|
||||
if ( (section_len = bacapp_decode_context_datetime(&apdu[len], TIME_STAMP_DATETIME, &value->value.dateTime)) == -1 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
len += section_len;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
|
||||
void testTimestampSequence(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_TIMESTAMP testTimestampIn;
|
||||
BACNET_TIMESTAMP testTimestampOut;
|
||||
uint8_t buffer[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
testTimestampIn.tag = TIME_STAMP_SEQUENCE;
|
||||
testTimestampIn.value.sequenceNum = 0x1234;
|
||||
|
||||
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
|
||||
|
||||
|
||||
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
|
||||
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
|
||||
ct_test(pTest, testTimestampIn.value.sequenceNum == testTimestampOut.value.sequenceNum);
|
||||
}
|
||||
|
||||
void testTimestampTime(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_TIMESTAMP testTimestampIn;
|
||||
BACNET_TIMESTAMP testTimestampOut;
|
||||
uint8_t buffer[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
testTimestampIn.tag = TIME_STAMP_TIME;
|
||||
testTimestampIn.value.time.hour = 1;
|
||||
testTimestampIn.value.time.min = 2;
|
||||
testTimestampIn.value.time.sec = 3;
|
||||
testTimestampIn.value.time.hundredths = 4;
|
||||
|
||||
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
|
||||
|
||||
|
||||
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
|
||||
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
|
||||
ct_test(pTest, testTimestampIn.value.time.hour == testTimestampOut.value.time.hour);
|
||||
ct_test(pTest, testTimestampIn.value.time.min == testTimestampOut.value.time.min);
|
||||
ct_test(pTest, testTimestampIn.value.time.sec == testTimestampOut.value.time.sec);
|
||||
ct_test(pTest, testTimestampIn.value.time.hundredths == testTimestampOut.value.time.hundredths);
|
||||
}
|
||||
|
||||
void testTimestampTimeDate(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_TIMESTAMP testTimestampIn;
|
||||
BACNET_TIMESTAMP testTimestampOut;
|
||||
uint8_t buffer[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
testTimestampIn.tag = TIME_STAMP_DATETIME;
|
||||
testTimestampIn.value.dateTime.time.hour = 1;
|
||||
testTimestampIn.value.dateTime.time.min = 2;
|
||||
testTimestampIn.value.dateTime.time.sec = 3;
|
||||
testTimestampIn.value.dateTime.time.hundredths = 4;
|
||||
|
||||
testTimestampIn.value.dateTime.date.year = 1901;
|
||||
testTimestampIn.value.dateTime.date.month = 1;
|
||||
testTimestampIn.value.dateTime.date.wday = 2;
|
||||
testTimestampIn.value.dateTime.date.day = 3;
|
||||
|
||||
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
|
||||
|
||||
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
|
||||
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.time.hour == testTimestampOut.value.dateTime.time.hour);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.time.min == testTimestampOut.value.dateTime.time.min);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.time.sec == testTimestampOut.value.dateTime.time.sec);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.time.hundredths == testTimestampOut.value.dateTime.time.hundredths);
|
||||
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.date.year == testTimestampOut.value.dateTime.date.year);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.date.month == testTimestampOut.value.dateTime.date.month);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.date.wday == testTimestampOut.value.dateTime.date.wday);
|
||||
ct_test(pTest, testTimestampIn.value.dateTime.date.day == testTimestampOut.value.dateTime.date.day);
|
||||
|
||||
}
|
||||
|
||||
#ifdef TEST_TIME_STAMP
|
||||
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Time Stamp", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testTimestampSequence);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testTimestampTime);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testTimestampTimeDate);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // TEST_TIME_STAMP
|
||||
#endif // TEST
|
||||
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2008 John Minack
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
The Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if other files instantiate templates or
|
||||
use macros or inline functions from this file, or you compile
|
||||
this file and link it with other works to produce a work based
|
||||
on this file, this file does not by itself cause the resulting
|
||||
work to be covered by the GNU General Public License. However
|
||||
the source code for this file must still be made available in
|
||||
accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work
|
||||
based on this file might be covered by the GNU General Public
|
||||
License.
|
||||
-------------------------------------------
|
||||
####COPYRIGHTEND####*/
|
||||
|
||||
#include "assert.h"
|
||||
#include "timestamp.h"
|
||||
|
||||
int bacapp_encode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value)
|
||||
{
|
||||
int len = 0; /* length of each encoding */
|
||||
int apdu_len = 0;
|
||||
|
||||
if (value && apdu) {
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
switch (value->tag) {
|
||||
case TIME_STAMP_TIME:
|
||||
len =
|
||||
encode_context_time(&apdu[apdu_len], 0,
|
||||
&value->value.time);
|
||||
break;
|
||||
|
||||
case TIME_STAMP_SEQUENCE:
|
||||
len =
|
||||
encode_context_unsigned(&apdu[apdu_len], 1,
|
||||
value->value.sequenceNum);
|
||||
break;
|
||||
|
||||
case TIME_STAMP_DATETIME:
|
||||
len =
|
||||
bacapp_encode_context_datetime(&apdu[apdu_len], 2,
|
||||
&value->value.dateTime);
|
||||
break;
|
||||
|
||||
default:
|
||||
len = 0;
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_context_timestamp(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIMESTAMP * value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_len;
|
||||
uint32_t len_value_type;
|
||||
uint32_t sequenceNum;
|
||||
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
|
||||
section_len =
|
||||
decode_tag_number_and_value(&apdu[len], &value->tag,
|
||||
&len_value_type);
|
||||
|
||||
if (-1 == section_len) {
|
||||
return -1;
|
||||
}
|
||||
switch (value->tag) {
|
||||
case TIME_STAMP_TIME:
|
||||
if ((section_len =
|
||||
decode_context_bacnet_time(&apdu[len], TIME_STAMP_TIME,
|
||||
&value->value.time)) == -1) {
|
||||
return -1;
|
||||
} else {
|
||||
len += section_len;
|
||||
}
|
||||
break;
|
||||
|
||||
case TIME_STAMP_SEQUENCE:
|
||||
if ((section_len =
|
||||
decode_context_unsigned(&apdu[len],
|
||||
TIME_STAMP_SEQUENCE, &sequenceNum)) == -1) {
|
||||
return -1;
|
||||
} else {
|
||||
if (sequenceNum <= 0xffff) {
|
||||
len += section_len;
|
||||
value->value.sequenceNum = (uint16_t) sequenceNum;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TIME_STAMP_DATETIME:
|
||||
if ((section_len =
|
||||
bacapp_decode_context_datetime(&apdu[len],
|
||||
TIME_STAMP_DATETIME,
|
||||
&value->value.dateTime)) == -1) {
|
||||
return -1;
|
||||
} else {
|
||||
len += section_len;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ctest.h"
|
||||
|
||||
|
||||
void testTimestampSequence(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_TIMESTAMP testTimestampIn;
|
||||
BACNET_TIMESTAMP testTimestampOut;
|
||||
uint8_t buffer[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
testTimestampIn.tag = TIME_STAMP_SEQUENCE;
|
||||
testTimestampIn.value.sequenceNum = 0x1234;
|
||||
|
||||
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
|
||||
|
||||
|
||||
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
|
||||
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.sequenceNum ==
|
||||
testTimestampOut.value.sequenceNum);
|
||||
}
|
||||
|
||||
void testTimestampTime(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_TIMESTAMP testTimestampIn;
|
||||
BACNET_TIMESTAMP testTimestampOut;
|
||||
uint8_t buffer[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
testTimestampIn.tag = TIME_STAMP_TIME;
|
||||
testTimestampIn.value.time.hour = 1;
|
||||
testTimestampIn.value.time.min = 2;
|
||||
testTimestampIn.value.time.sec = 3;
|
||||
testTimestampIn.value.time.hundredths = 4;
|
||||
|
||||
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
|
||||
|
||||
|
||||
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
|
||||
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.time.hour == testTimestampOut.value.time.hour);
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.time.min == testTimestampOut.value.time.min);
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.time.sec == testTimestampOut.value.time.sec);
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.time.hundredths ==
|
||||
testTimestampOut.value.time.hundredths);
|
||||
}
|
||||
|
||||
void testTimestampTimeDate(
|
||||
Test * pTest)
|
||||
{
|
||||
BACNET_TIMESTAMP testTimestampIn;
|
||||
BACNET_TIMESTAMP testTimestampOut;
|
||||
uint8_t buffer[MAX_APDU];
|
||||
int inLen;
|
||||
int outLen;
|
||||
|
||||
testTimestampIn.tag = TIME_STAMP_DATETIME;
|
||||
testTimestampIn.value.dateTime.time.hour = 1;
|
||||
testTimestampIn.value.dateTime.time.min = 2;
|
||||
testTimestampIn.value.dateTime.time.sec = 3;
|
||||
testTimestampIn.value.dateTime.time.hundredths = 4;
|
||||
|
||||
testTimestampIn.value.dateTime.date.year = 1901;
|
||||
testTimestampIn.value.dateTime.date.month = 1;
|
||||
testTimestampIn.value.dateTime.date.wday = 2;
|
||||
testTimestampIn.value.dateTime.date.day = 3;
|
||||
|
||||
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
|
||||
|
||||
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
|
||||
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
|
||||
|
||||
ct_test(pTest, inLen == outLen);
|
||||
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.dateTime.time.hour ==
|
||||
testTimestampOut.value.dateTime.time.hour);
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.dateTime.time.min ==
|
||||
testTimestampOut.value.dateTime.time.min);
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.dateTime.time.sec ==
|
||||
testTimestampOut.value.dateTime.time.sec);
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.dateTime.time.hundredths ==
|
||||
testTimestampOut.value.dateTime.time.hundredths);
|
||||
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.dateTime.date.year ==
|
||||
testTimestampOut.value.dateTime.date.year);
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.dateTime.date.month ==
|
||||
testTimestampOut.value.dateTime.date.month);
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.dateTime.date.wday ==
|
||||
testTimestampOut.value.dateTime.date.wday);
|
||||
ct_test(pTest,
|
||||
testTimestampIn.value.dateTime.date.day ==
|
||||
testTimestampOut.value.dateTime.date.day);
|
||||
|
||||
}
|
||||
|
||||
#ifdef TEST_TIME_STAMP
|
||||
|
||||
int main(
|
||||
void)
|
||||
{
|
||||
Test *pTest;
|
||||
bool rc;
|
||||
|
||||
pTest = ct_create("BACnet Time Stamp", NULL);
|
||||
/* individual tests */
|
||||
rc = ct_addTestFunction(pTest, testTimestampSequence);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testTimestampTime);
|
||||
assert(rc);
|
||||
|
||||
rc = ct_addTestFunction(pTest, testTimestampTimeDate);
|
||||
assert(rc);
|
||||
|
||||
ct_setStream(pTest, stdout);
|
||||
ct_run(pTest);
|
||||
(void) ct_report(pTest);
|
||||
ct_destroy(pTest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // TEST_TIME_STAMP
|
||||
#endif // TEST
|
||||
|
||||
@@ -88,7 +88,7 @@ int whohas_decode_service_request(
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value = 0;
|
||||
uint32_t decoded_value = 0; /* for decoding */
|
||||
uint16_t decoded_type = 0; /* for decoding */
|
||||
uint16_t decoded_type = 0; /* for decoding */
|
||||
|
||||
if (apdu_len && data) {
|
||||
/* optional limits - must be used as a pair */
|
||||
|
||||
@@ -99,7 +99,7 @@ int wp_decode_service_request(
|
||||
int tag_len = 0;
|
||||
uint8_t tag_number = 0;
|
||||
uint32_t len_value_type = 0;
|
||||
uint16_t type = 0; /* for decoding */
|
||||
uint16_t type = 0; /* for decoding */
|
||||
int property = 0; /* for decoding */
|
||||
uint32_t unsigned_value = 0;
|
||||
int i = 0; /* loop counter */
|
||||
|
||||
Reference in New Issue
Block a user