Added sample Confirmed Private Transfer implementation files and demo for same.

This commit is contained in:
petermcs
2009-09-04 11:25:47 +00:00
parent de35ce7c5e
commit 8d80d25322
13 changed files with 2183 additions and 11 deletions
+255
View File
@@ -0,0 +1,255 @@
/**************************************************************************
*
* 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 "apdu.h"
#include "npdu.h"
#include "abort.h"
//#include "arf.h"
/* demo objects */
#include "device.h"
#include "ai.h"
#include "ao.h"
#if defined(BACFILE)
#include "bacfile.h"
#endif
#include "mydata.h"
#include "ptransfer.h"
#define MYMAXSTR 32
#define MYMAXBLOCK 8
DATABLOCK MyData[MYMAXBLOCK];
uint8_t IOBufferPT[MAX_APDU]; // Buffer for building response in
void ProcessPT(BACNET_PRIVATE_TRANSFER_DATA *data)
{
int iLen; // Index to current location in data
char cBlockNumber;
uint32_t ulTemp;
int tag_len;
uint8_t tag_number;
uint32_t len_value_type;
BACNET_CHARACTER_STRING bsTemp;
iLen = 0;
// Decode the block number
tag_len = decode_tag_number_and_value(&data->serviceParameters[iLen], &tag_number, &len_value_type);
iLen += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) { // Bail out early if wrong type
data->serviceParametersLen = 0; // and signal unexpected error
return;
}
iLen += decode_unsigned(&data->serviceParameters[iLen], len_value_type, &ulTemp);
cBlockNumber = (char)ulTemp;
if(cBlockNumber < MY_MAX_BLOCK) {
if(data->serviceNumber == MY_SVC_READ) {
// Read Response is an unsigned int with 0 for success or a non 0 error code
// For a successful read the 0 success code is followed by the block number
// and then the block contents which consist of 2 unsigned ints (in 0 to 255
// range as they are really chars) a single precision real and a string which
// will be up to 32 chars + a nul
iLen = 0;
iLen += encode_application_unsigned(&IOBufferPT[iLen], MY_ERR_OK); // Signal success
iLen += encode_application_unsigned(&IOBufferPT[iLen], cBlockNumber); // Followed by the block number
iLen += encode_application_unsigned(&IOBufferPT[iLen], MyData[cBlockNumber].cMyByte1); // And Then the block contents
iLen += encode_application_unsigned(&IOBufferPT[iLen], MyData[cBlockNumber].cMyByte2);
iLen += encode_application_real(&IOBufferPT[iLen], MyData[cBlockNumber].fMyReal);
characterstring_init_ansi(&bsTemp, MyData[cBlockNumber].sMyString);
iLen += encode_application_character_string(&IOBufferPT[iLen], &bsTemp);
}
else { // Write operation
// Write block consists of the block number followed by the block contents as
// described above for the read operation. The returned result is an unsigned
// response which is 0 for success and a non 0 error code otherwise.
tag_len = decode_tag_number_and_value(&data->serviceParameters[iLen], &tag_number, &len_value_type);
iLen += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) {
data->serviceParametersLen = 0;
return;
}
iLen += decode_unsigned(&data->serviceParameters[iLen], len_value_type, &ulTemp);
MyData[cBlockNumber].cMyByte1 = (char)ulTemp;
tag_len = decode_tag_number_and_value(&data->serviceParameters[iLen], &tag_number, &len_value_type);
iLen += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) {
data->serviceParametersLen = 0;
return;
}
iLen += decode_unsigned(&data->serviceParameters[iLen], len_value_type, &ulTemp);
MyData[cBlockNumber].cMyByte2 = (char)ulTemp;
tag_len = decode_tag_number_and_value(&data->serviceParameters[iLen], &tag_number, &len_value_type);
iLen += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_REAL) {
data->serviceParametersLen = 0;
return;
}
iLen += decode_real(&data->serviceParameters[iLen], &MyData[cBlockNumber].fMyReal);
tag_len = decode_tag_number_and_value(&data->serviceParameters[iLen], &tag_number, &len_value_type);
iLen += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_CHARACTER_STRING) {
data->serviceParametersLen = 0;
return;
}
decode_character_string(&data->serviceParameters[iLen], len_value_type, &bsTemp);
strncpy(MyData[cBlockNumber].sMyString, characterstring_value(&bsTemp), MY_MAX_STR); // Only copy as much as we can accept
MyData[cBlockNumber].sMyString[MY_MAX_STR] = '\0'; // Make sure it is nul terminated
iLen = encode_application_unsigned(&IOBufferPT[0], MY_ERR_OK); // Signal success
}
}
else {
iLen = encode_application_unsigned(&IOBufferPT[0], MY_ERR_BAD_INDEX); // Signal bad index
}
data->serviceParametersLen = iLen;
data->serviceParameters = IOBufferPT;
}
/*
* This is called when we receive a private transfer packet.
* We parse the data, send the private part for processing and then send the
* response which the application generates.
* If there are any BACnet level errors we send an error response from here.
* If there are any application level errors they will be packeged up in the
* response block which we send back to the originator of the request.
*
*/
void handler_conf_private_trans(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_PRIVATE_TRANSFER_DATA data;
int len;
int pdu_len;
bool error;
int bytes_sent;
BACNET_NPDU_DATA npdu_data;
BACNET_ADDRESS my_address;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
len = 0;
pdu_len = 0;
error = false;
bytes_sent = 0;
error_class = ERROR_CLASS_OBJECT;
error_code = ERROR_CODE_UNKNOWN_OBJECT;
#if PRINT_ENABLED
fprintf(stderr,"Received Confirmed Private Transfer Request!\n");
#endif
// encode the NPDU portion of the response packet as it will be needed
// no matter what the outcome.
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)
{
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
#if PRINT_ENABLED
fprintf(stderr,"CPT: Segmented Message. Sending Abort!\n");
#endif
goto CPT_ABORT;
}
len = ptransfer_decode_service_request(service_request, service_len, &data);
/* bad decoding - send an abort */
if (len < 0)
{
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, ABORT_REASON_OTHER, true);
#if PRINT_ENABLED
fprintf(stderr,"CPT: Bad Encoding. Sending Abort!\n");
#endif
goto CPT_ABORT;
}
// Simple example with service number of 0 for read block and 1 for write block
// We also only support our own vendor ID. In theory we could support others
// for compatability purposes but these interfaces are rarely documented...
if((data.vendorID == BACNET_VENDOR_ID) && (data.serviceNumber <= MY_SVC_WRITE)){ // We only try to understand our own IDs and service numbers
ProcessPT(&data); // Will either return a result block or an app level status block
if(data.serviceParametersLen == 0){ // No respopnse means fatal error
error = true;
error_class = ERROR_CLASS_SERVICES;
error_code = ERROR_CODE_OTHER;
#if PRINT_ENABLED
fprintf(stderr,"CPT: Error servicing request!\n");
#endif
}
len = ptransfer_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, &data);
}
else // Not our vendor ID or bad service parameter
{
error = true;
error_class = ERROR_CLASS_SERVICES;
error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
#if PRINT_ENABLED
fprintf(stderr,"CPT: Not our Vendor ID or invalid service code!\n");
#endif
}
if (error){
len = ptransfer_error_encode_apdu(&Handler_Transmit_Buffer[pdu_len], service_data->invoke_id, error_class, error_code, &data);
}
CPT_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len);
#if PRINT_ENABLED
if (bytes_sent <= 0)
{
fprintf(stderr,"Failed to send PDU (%s)!\n",
strerror(errno));
}
#endif
return;
}
+226
View File
@@ -0,0 +1,226 @@
/**************************************************************************
*
* 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 "apdu.h"
#include "npdu.h"
#include "abort.h"
//#include "arf.h"
/* demo objects */
#include "device.h"
#include "ai.h"
#include "ao.h"
#include "ptransfer.h"
#include "mydata.h"
#if defined(BACFILE)
#include "bacfile.h"
#endif
extern uint8_t IOBufferPT[300]; // Somewhere to build the encoded result block for Private Transfers
void DecodeBlock(char cBlockNum, uint8_t *pData)
{
int iLen;
uint32_t ulTemp;
int tag_len;
uint8_t tag_number;
uint32_t len_value_type;
BACNET_CHARACTER_STRING bsName;
DATABLOCK Response;
iLen = 0;
if(cBlockNum >= MY_MAX_BLOCK)
return;
tag_len = decode_tag_number_and_value(&pData[iLen], &tag_number, &len_value_type);
iLen += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return;
iLen += decode_unsigned(&pData[iLen], len_value_type, &ulTemp);
Response.cMyByte1 = (char)ulTemp;
tag_len = decode_tag_number_and_value(&pData[iLen], &tag_number, &len_value_type);
iLen += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT)
return;
iLen += decode_unsigned(&pData[iLen], len_value_type, &ulTemp);
Response.cMyByte2 = (char)ulTemp;
tag_len = decode_tag_number_and_value(&pData[iLen], &tag_number, &len_value_type);
iLen += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_REAL)
return;
iLen += decode_real(&pData[iLen], &Response.fMyReal);
tag_len = decode_tag_number_and_value(&pData[iLen], &tag_number, &len_value_type);
iLen += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_CHARACTER_STRING)
return;
iLen += decode_character_string(&pData[iLen], len_value_type, &bsName);
strncpy(Response.sMyString, characterstring_value(&bsName), MY_MAX_STR);
Response.sMyString[MY_MAX_STR] = '\0'; // Make sure it is nul terminated
printf("Private Transfer Read Block Response\n");
printf("Data Block: %d\n", (int)cBlockNum);
printf(" First Byte : %d\n", (int)Response.cMyByte1);
printf(" Second Byte : %d\n", (int)Response.cMyByte2);
printf(" Real : %f\n", Response.fMyReal);
printf(" String : %s\n\n", Response.sMyString);
}
void ProcessPTA(BACNET_PRIVATE_TRANSFER_DATA *data)
{
int iLen; // Index to current location in data
uint32_t uiErrorCode;
char cBlockNumber;
uint32_t ulTemp;
int tag_len;
uint8_t tag_number;
uint32_t len_value_type;
iLen = 0;
// Error code is returned for read and write operations
tag_len = decode_tag_number_and_value(&data->serviceParameters[iLen], &tag_number, &len_value_type);
iLen += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) {
#if PRINT_ENABLED
printf("CPTA: Bad Encoding!\n");
#endif
return;
}
iLen += decode_unsigned(&data->serviceParameters[iLen], len_value_type, &uiErrorCode);
if(data->serviceNumber == MY_SVC_READ) { // Read I/O block so should be full block of data or error
// Decode the error type and if necessary block number and then fetch the info
if(uiErrorCode == MY_ERR_OK) {
// Block Number
tag_len = decode_tag_number_and_value(&data->serviceParameters[iLen], &tag_number, &len_value_type);
iLen += tag_len;
if (tag_number != BACNET_APPLICATION_TAG_UNSIGNED_INT) {
#if PRINT_ENABLED
printf("CPTA: Bad Encoding!\n");
#endif
return;
}
iLen += decode_unsigned(&data->serviceParameters[iLen], len_value_type, &ulTemp);
cBlockNumber = (char)ulTemp;
DecodeBlock(cBlockNumber, &data->serviceParameters[iLen]);
}
else { // Read error
printf("Private Transfer read operation returned error code: %u\n", uiErrorCode);
return;
}
}
else { // Write I/O block - should just be an OK type message
printf("Private Transfer write operation returned error code: %u\n", uiErrorCode);
}
}
/*
* This is called when we receive a private transfer packet ack.
* We parse the response which the remote application generated
* and decide what to do next...
*/
void handler_conf_private_trans_ack(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data)
{
BACNET_PRIVATE_TRANSFER_DATA data;
int len;
/*
* Note:
* We currently don't look at the source address and service data
* but we probably should to verify that the ack is oneit is what
* we were expecting. But this is just to silence some compiler
* warnings from Borland.
*/
src = src;
service_data = service_data;
len = 0;
#if PRINT_ENABLED
printf("Received Confirmed Private Transfer Ack!\n");
#endif
len = ptransfer_decode_service_request(service_request, service_len, &data); // Same decode for ack as for service request!
if (len < 0)
{
#if PRINT_ENABLED
printf("cpta: Bad Encoding!\n");
#endif
}
ProcessPTA(&data); // See what to do with the response
return;
}
#if 0
void PTErrorHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Error: %s: %s\r\n",
bactext_error_class_name((int) error_class),
bactext_error_code_name((int) error_code));
Error_Detected = true;
}
#endif
+140
View File
@@ -0,0 +1,140 @@
/**************************************************************************
*
* 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.
*
*********************************************************************/
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <errno.h>
#include <string.h>
#include "config.h"
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "address.h"
#include "tsm.h"
#include "npdu.h"
#include "apdu.h"
#include "device.h"
#include "datalink.h"
#include "dcc.h"
#include "ptransfer.h"
/* some demo stuff needed */
#include "handlers.h"
#include "txbuf.h"
#include "mydata.h"
uint8_t Send_Private_Transfer_Request(
uint32_t device_id,
uint16_t vendor_id,
uint32_t service_number,
char block_number,
DATABLOCK *block
)
{ /* NULL=optional */
BACNET_ADDRESS dest;
BACNET_ADDRESS my_address;
unsigned max_apdu = 0;
uint8_t invoke_id = 0;
bool status = false;
int len = 0;
int pdu_len = 0;
int bytes_sent = 0;
BACNET_NPDU_DATA npdu_data;
static uint8_t pt_req_buffer[300]; // Somewhere to build the request packet
BACNET_PRIVATE_TRANSFER_DATA pt_block;
BACNET_CHARACTER_STRING bsTemp;
/* if we are forbidden to send, don't send! */
if (!dcc_communication_enabled())
return 0;
/* is the device bound? */
status = address_get_by_device(device_id, &max_apdu, &dest);
/* is there a tsm available? */
if (status)
invoke_id = tsm_next_free_invokeID();
if (invoke_id) {
/* 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(&Handler_Transmit_Buffer[0], &dest, &my_address,
&npdu_data);
/* encode the APDU portion of the packet */
pt_block.vendorID = vendor_id;
pt_block.serviceNumber = service_number;
if(service_number == MY_SVC_READ)
{
len += encode_application_unsigned(&pt_req_buffer[len], block_number); // The block number we want to retrieve
}
else
{
len += encode_application_unsigned(&pt_req_buffer[len], block_number); // The block number
len += encode_application_unsigned(&pt_req_buffer[len], block->cMyByte1); // And Then the block contents
len += encode_application_unsigned(&pt_req_buffer[len], block->cMyByte2);
len += encode_application_real(&pt_req_buffer[len], block->fMyReal);
characterstring_init_ansi(&bsTemp, block->sMyString);
len += encode_application_character_string(&pt_req_buffer[len], &bsTemp);
}
pt_block.serviceParameters = &pt_req_buffer[0];
pt_block.serviceParametersLen = len;
len = ptransfer_encode_apdu(&Handler_Transmit_Buffer[pdu_len], invoke_id, &pt_block);
pdu_len += len;
/* will it fit in the sender?
note: if there is a bottleneck router in between
us and the destination, we won't know unless
we have a way to check for that and update the
max_apdu in the address binding table. */
if ((unsigned) pdu_len < max_apdu) {
tsm_set_confirmed_unsegmented_transaction(invoke_id, &dest,
&npdu_data, &Handler_Transmit_Buffer[0], pdu_len);
bytes_sent =
datalink_send_pdu(&dest, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
#if PRINT_ENABLED
if (bytes_sent <= 0)
fprintf(stderr,
"Failed to Send Private Transfer Request (%s)!\n",
strerror(errno));
#endif
} else {
tsm_free_invoke_id(invoke_id);
invoke_id = 0;
#if PRINT_ENABLED
fprintf(stderr,
"Failed to Send Private Transfer Request "
"(exceeds destination maximum APDU)!\n");
#endif
}
}
return invoke_id;
}
+371
View File
@@ -0,0 +1,371 @@
/*************************************************************************
* 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.
*
*********************************************************************/
/* command line tool that sends a BACnet service, and displays the reply */
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h> /* for time */
#include <conio.h>
#define PRINT_ENABLED 1
#include "bacdef.h"
#include "config.h"
#include "bactext.h"
#include "bacerror.h"
#include "iam.h"
#include "arf.h"
#include "tsm.h"
#include "address.h"
#include "npdu.h"
#include "apdu.h"
#include "device.h"
#include "net.h"
#include "datalink.h"
#include "whois.h"
/* some demo stuff needed */
#include "filename.h"
#include "handlers.h"
#include "client.h"
#include "txbuf.h"
#include "dlenv.h"
#include "mydata.h"
#if defined(__BORLANDC__)
#define _kbhit kbhit
#define _stricmp stricmp
#endif
uint8_t Send_Private_Transfer_Request(
uint32_t device_id,
uint16_t vendor_id,
uint32_t service_number,
char block_number,
DATABLOCK *block);
/* buffer used for receive */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
/* global variables used in this file */
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
static int Target_Mode = 0;
static BACNET_ADDRESS Target_Address;
static bool Error_Detected = false;
static void MyErrorHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
BACNET_ERROR_CLASS error_class,
BACNET_ERROR_CODE error_code)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Error: %s: %s\r\n",
bactext_error_class_name((int) error_class),
bactext_error_code_name((int) error_code));
// Error_Detected = true;
}
void MyAbortHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t abort_reason,
bool server)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
(void) server;
printf("BACnet Abort: %s\r\n",
bactext_abort_reason_name((int) abort_reason));
Error_Detected = true;
}
void MyRejectHandler(
BACNET_ADDRESS * src,
uint8_t invoke_id,
uint8_t reject_reason)
{
/* FIXME: verify src and invoke id */
(void) src;
(void) invoke_id;
printf("BACnet Reject: %s\r\n",
bactext_reject_reason_name((int) reject_reason));
Error_Detected = true;
}
static void Init_Service_Handlers(
void)
{
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* handle i-am to support binding to other devices */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM, handler_i_am_bind);
/* set the handler for all the services we don't implement
It is required to send the proper reject message... */
apdu_set_unrecognized_service_handler_handler
(handler_unrecognized_service);
/* we must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_PRIVATE_TRANSFER,
handler_conf_private_trans);
/* handle the data coming back from confirmed requests */
apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property_ack);
apdu_set_confirmed_ack_handler(SERVICE_CONFIRMED_PRIVATE_TRANSFER,
handler_conf_private_trans_ack);
/* handle any errors coming back */
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler);
apdu_set_error_handler(SERVICE_CONFIRMED_PRIVATE_TRANSFER, MyErrorHandler);
apdu_set_abort_handler(MyAbortHandler);
apdu_set_reject_handler(MyRejectHandler);
}
int main(
int argc,
char *argv[])
{
BACNET_ADDRESS src = {
0
}; /* address where message came from */
uint16_t pdu_len = 0;
unsigned timeout = 100; /* milliseconds */
unsigned max_apdu = 0;
time_t elapsed_seconds = 0;
time_t last_seconds = 0;
time_t current_seconds = 0;
time_t timeout_seconds = 0;
uint8_t invoke_id = 0;
bool found = false;
DATABLOCK NewData;
int iCount = 0;
int iType = 0;
int iKey;
static int iLimit[3] = {7, 11, 7};
if (((argc != 2) && (argc != 3)) || ((argc >= 2) && (strcmp(argv[1], "--help") == 0))) {
printf("%s\n",argv[0]);
printf("Usage: %s server local-device-instance\r\n or\r\n"
" %s remote-device-instance\r\n"
, filename_remove_path(argv[0]), filename_remove_path(argv[0]));
if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
printf("\r\nServer mode:\r\n\r\n"
"local-device-instance determins the device id of the application\r\n"
"when running as the server end of a test set up.\r\n\r\n"
"Non server:\r\n\r\n"
"remote-device-instance indicates the device id of the server\r\n"
"instance of the application.\r\n"
"The non server application will write a series of blocks to the\r\n"
"server and then retrieve them for display locally\r\n"
"First it writes all 8 blocks plus a 9th which should trigger\r\n"
"an out of range error response. Then it reads all the blocks\r\n"
"including the ninth and finally it repeats the read operation\r\n"
"with some deliberate errors to trigger a nack response\r\n");
}
return 0;
}
/* decode the command line parameters */
if(_stricmp(argv[1], "server") == 0)
Target_Mode = 1;
else
Target_Mode = 0;
Target_Device_Object_Instance = strtol(argv[1 + Target_Mode], NULL, 0);
if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
/* setup my info */
if(Target_Mode)
Device_Set_Object_Instance_Number(Target_Device_Object_Instance);
else
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init();
Init_Service_Handlers();
dlenv_init();
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
if(Target_Mode) {
printf("Entering server mode. press q to quit program\r\n\r\n");
for (;;) {
/* increment timer - exit if timed out */
current_seconds = time(NULL);
if(current_seconds != last_seconds) {
}
/* returns 0 bytes on timeout */
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
/* at least one second has passed */
if (current_seconds != last_seconds) {
putchar('.'); // Just to show that time is passing...
last_seconds = current_seconds;
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
}
if(_kbhit()) {
iKey = toupper(_getch());
if(iKey == 'Q') {
printf("\r\nExiting program now\r\n");
exit(0);
}
}
}
}
else {
/* try to bind with the device */
found =
address_bind_request(Target_Device_Object_Instance, &max_apdu,
&Target_Address);
if (!found) {
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
}
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
current_seconds = time(NULL);
/* returns 0 bytes on timeout */
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
/* process */
if (pdu_len) {
npdu_handler(&src, &Rx_Buf[0], pdu_len);
}
/* at least one second has passed */
if (current_seconds != last_seconds)
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
if (Error_Detected)
break;
/* wait until the device is bound, or timeout and quit */
if(!found)
found = address_bind_request(Target_Device_Object_Instance, &max_apdu, &Target_Address);
if (found)
{
if (invoke_id == 0) { // Safe to send a new request
switch(iType) {
case 0: // Write blocks to server
NewData.cMyByte1 = iCount;
NewData.cMyByte2 = 255 - iCount;
NewData.fMyReal = (float)iCount;
strcpy(NewData.sMyString, "Test Data - [x]");
NewData.sMyString[13] = 'a' + iCount;
printf("Sending block %d\n", iCount);
invoke_id = Send_Private_Transfer_Request(Target_Device_Object_Instance, BACNET_VENDOR_ID, 1, iCount, &NewData);
break;
case 1: // Read blocks from server
printf("Requesting block %d\n", iCount);
invoke_id = Send_Private_Transfer_Request(Target_Device_Object_Instance, BACNET_VENDOR_ID, 0, iCount, &NewData);
break;
case 2: // Generate some error responses
switch(iCount) {
case 0: // Bad service number i.e. 2
case 2:
case 4:
case 6:
case 8:
printf("Requesting block %d with bad service number\n", iCount);
invoke_id = Send_Private_Transfer_Request(Target_Device_Object_Instance, BACNET_VENDOR_ID, 2, iCount, &NewData);
break;
case 1: // Bad vendor ID number
case 3:
case 5:
case 7:
printf("Requesting block %d with invalid Vendor ID\n", iCount);
invoke_id = Send_Private_Transfer_Request(Target_Device_Object_Instance, BACNET_VENDOR_ID + 1, 0, iCount, &NewData);
break;
}
break;
}
}
else if (tsm_invoke_id_free(invoke_id)) {
if(iCount != MY_MAX_BLOCK) {
iCount++;
invoke_id = 0;
}
else {
iType++;
iCount = 0;
invoke_id = 0;
if(iType > 2)
break;
}
}
else if (tsm_invoke_id_failed(invoke_id))
{
fprintf(stderr, "\rError: TSM Timeout!\r\n");
tsm_free_invoke_id(invoke_id);
Error_Detected = true;
/* try again or abort? */
break;
}
}
else
{
/* increment timer - exit if timed out */
elapsed_seconds += (current_seconds - last_seconds);
if (elapsed_seconds > timeout_seconds) {
printf("\rError: APDU Timeout!\r\n");
Error_Detected = true;
break;
}
}
/* keep track of time for next check */
last_seconds = current_seconds;
}
}
if (Error_Detected)
return 1;
return 0;
}
+134
View File
@@ -0,0 +1,134 @@
#
# Simple makefile to build an executable for Win32
#
# This makefile assumes Borland bcc32 development environment
# on Windows NT/9x/2000/XP
#
!ifndef BORLAND_DIR
BORLAND_DIR_Not_Defined:
@echo .
@echo You must define environment variable BORLAND_DIR to compile.
!endif
PRODUCT = ptransfer
PRODUCT_EXE = $(PRODUCT).exe
# tools
CC = $(BORLAND_DIR)\bin\bcc32
MAKE=$(BORLAND_DIR)\bin\make.exe
#LINK = $(BORLAND_DIR)\bin\tlink32
LINK = $(BORLAND_DIR)\bin\ilink32
BACNET_LIB_DIR = ..\..\lib
BACNET_LIB = $(BACNET_LIB_DIR)\bacnet.lib
# directories
BACNET_PORT = ..\..\ports\win32
BACNET_INCLUDE = ..\..\include
INCLUDES = \
-I$(BACNET_INCLUDE) \
-I$(BACNET_PORT) \
-I$(BORLAND_DIR)\include
#
BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
#BACDL_DEFINE=-DBACDL_MSTP=1
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
SRCS = main.c
OBJS = $(SRCS:.c=.obj)
#
# Compiler definitions
#
BCC_CFG = bcc32.cfg
#
# Include directories
#
CFLAGS = $(INCLUDES) $(DEFINES)
#
# Libraries
#
C_LIB_DIR = $(BORLAND_DIR)\lib
LIBS = $(BACNET_LIB) \
$(C_LIB_DIR)\IMPORT32.lib \
$(C_LIB_DIR)\CW32MT.lib \
#
# Main target
#
# This should be the first one in the makefile
all : $(BACNET_LIB) $(BCC_CFG) $(OBJS) $(PRODUCT_EXE)
del $(BCC_CFG)
install: $(PRODUCT_EXE)
copy $(PRODUCT_EXE) ..\..\bin\$(PRODUCT_EXE)
# Linker specific: the link below is for BCC linker/compiler. If you link
# with a different linker - please change accordingly.
#
# need a temp response file (@&&| ... |) because command line is too long
# $** lists each dependency
# $< target name
# $* target name without extension
$(PRODUCT_EXE) : $(OBJS)
@echo Running Linker for $(PRODUCT_EXE)
$(LINK) -L$(C_LIB_DIR) -L$(BACNET_LIB_DIR) -m -c -s -v @&&|
$(BORLAND_DIR)\lib\c0x32.obj $**
$<
$*.map
$(LIBS)
|
#
# Utilities
clean :
del $(OBJS)
del $(PRODUCT_EXE)
del $(PRODUCT).map
del $(PRODUCT).ilc
del $(PRODUCT).ild
del $(PRODUCT).ilf
del $(PRODUCT).ils
del $(PRODUCT).tds
del $(BCC_CFG)
#
# Generic rules
#
.SUFFIXES: .cpp .c .sbr .obj
#
# cc generic rule
#
.c.obj:
$(CC) +$(BCC_CFG) -o$@ $<
# Compiler configuration file
$(BCC_CFG) :
Copy &&|
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
-Od #disable all optimizations
#-a4 #32 bit data alignment
#-M # generate link map
#-ls # linker options
#-WM- #not multithread
-WM #multithread
-w-aus # ignore warning assigned a value that is never used
-w-sig # ignore warning conversion may lose sig digits
| $@
# EOF: makefile
+20
View File
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rdproperty", "rdproperty.vcproj", "{7AC60281-278A-4060-B900-A1343E438701}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7AC60281-278A-4060-B900-A1343E438701}.Debug|Win32.ActiveCfg = Debug|Win32
{7AC60281-278A-4060-B900-A1343E438701}.Debug|Win32.Build.0 = Debug|Win32
{7AC60281-278A-4060-B900-A1343E438701}.Release|Win32.ActiveCfg = Release|Win32
{7AC60281-278A-4060-B900-A1343E438701}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,967 @@
<?xml version="1.0" encoding="UTF-8"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="ptransfer"
ProjectGUID="{7AC60281-278A-4060-B900-A1343E438701}"
RootNamespace="ptransfer"
Keyword="Win32Proj"
TargetFrameworkVersion="0"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="&quot;..\..\ports\win32&quot;;&quot;..\..\include&quot;;."
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="false"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="wsock32.lib Iphlpapi.lib"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\..\include\abort.h"
>
</File>
<File
RelativePath="..\..\include\address.h"
>
</File>
<File
RelativePath="..\..\include\ai.h"
>
</File>
<File
RelativePath="..\..\include\alarm_ack.h"
>
</File>
<File
RelativePath="..\..\include\ao.h"
>
</File>
<File
RelativePath="..\..\include\apdu.h"
>
</File>
<File
RelativePath="..\..\include\arcnet.h"
>
</File>
<File
RelativePath="..\..\include\arf.h"
>
</File>
<File
RelativePath="..\..\include\av.h"
>
</File>
<File
RelativePath="..\..\include\awf.h"
>
</File>
<File
RelativePath="..\..\include\bacaddr.h"
>
</File>
<File
RelativePath="..\..\include\bacapp.h"
>
</File>
<File
RelativePath="..\..\include\bacdcode.h"
>
</File>
<File
RelativePath="..\..\include\bacdef.h"
>
</File>
<File
RelativePath="..\..\include\bacdevobjpropref.h"
>
</File>
<File
RelativePath="..\..\include\bacenum.h"
>
</File>
<File
RelativePath="..\..\include\bacerror.h"
>
</File>
<File
RelativePath="..\..\include\bacfile.h"
>
</File>
<File
RelativePath="..\..\include\bacint.h"
>
</File>
<File
RelativePath="..\..\include\bacnet.h"
>
</File>
<File
RelativePath="..\..\include\bacprop.h"
>
</File>
<File
RelativePath="..\..\include\bacpropstates.h"
>
</File>
<File
RelativePath="..\..\include\bacreal.h"
>
</File>
<File
RelativePath="..\..\include\bacstr.h"
>
</File>
<File
RelativePath="..\..\include\bactext.h"
>
</File>
<File
RelativePath="..\..\include\bi.h"
>
</File>
<File
RelativePath="..\..\include\bigend.h"
>
</File>
<File
RelativePath="..\..\include\bip.h"
>
</File>
<File
RelativePath="..\..\include\bits.h"
>
</File>
<File
RelativePath="..\..\include\bo.h"
>
</File>
<File
RelativePath="..\..\include\bv.h"
>
</File>
<File
RelativePath="..\..\include\bvlc.h"
>
</File>
<File
RelativePath="..\..\include\bytes.h"
>
</File>
<File
RelativePath="..\..\include\client.h"
>
</File>
<File
RelativePath="..\..\include\config.h"
>
</File>
<File
RelativePath="..\..\include\cov.h"
>
</File>
<File
RelativePath="..\..\include\crc.h"
>
</File>
<File
RelativePath="..\..\include\datalink.h"
>
</File>
<File
RelativePath="..\..\include\datetime.h"
>
</File>
<File
RelativePath="..\..\include\dcc.h"
>
</File>
<File
RelativePath="..\..\include\debug.h"
>
</File>
<File
RelativePath="..\..\include\device.h"
>
</File>
<File
RelativePath="..\..\include\dlenv.h"
>
</File>
<File
RelativePath="..\..\include\dlmstp.h"
>
</File>
<File
RelativePath="..\..\include\ethernet.h"
>
</File>
<File
RelativePath="..\..\include\event.h"
>
</File>
<File
RelativePath="..\..\include\fifo.h"
>
</File>
<File
RelativePath="..\..\include\filename.h"
>
</File>
<File
RelativePath="..\..\include\handlers.h"
>
</File>
<File
RelativePath="..\..\include\iam.h"
>
</File>
<File
RelativePath="..\..\include\ihave.h"
>
</File>
<File
RelativePath="..\..\include\indtext.h"
>
</File>
<File
RelativePath="..\..\include\key.h"
>
</File>
<File
RelativePath="..\..\include\keylist.h"
>
</File>
<File
RelativePath="..\..\include\lc.h"
>
</File>
<File
RelativePath="..\..\include\lo.h"
>
</File>
<File
RelativePath="..\..\include\lso.h"
>
</File>
<File
RelativePath="..\..\include\lsp.h"
>
</File>
<File
RelativePath="..\..\include\memcopy.h"
>
</File>
<File
RelativePath="..\..\include\mso.h"
>
</File>
<File
RelativePath="..\..\include\mstp.h"
>
</File>
<File
RelativePath="..\..\include\mstptext.h"
>
</File>
<File
RelativePath="..\..\include\mydata.h"
>
</File>
<File
RelativePath="..\..\include\npdu.h"
>
</File>
<File
RelativePath="..\..\include\nrg.h"
>
</File>
<File
RelativePath="..\..\include\objects.h"
>
</File>
<File
RelativePath="..\..\include\ptransfer.h"
>
</File>
<File
RelativePath="..\..\include\rd.h"
>
</File>
<File
RelativePath="..\..\include\reject.h"
>
</File>
<File
RelativePath="..\..\include\ringbuf.h"
>
</File>
<File
RelativePath="..\..\include\rp.h"
>
</File>
<File
RelativePath="..\..\include\rpm.h"
>
</File>
<File
RelativePath="..\..\include\sbuf.h"
>
</File>
<File
RelativePath="..\..\include\timestamp.h"
>
</File>
<File
RelativePath="..\..\include\timesync.h"
>
</File>
<File
RelativePath="..\..\include\tsm.h"
>
</File>
<File
RelativePath="..\..\include\txbuf.h"
>
</File>
<File
RelativePath="..\..\include\version.h"
>
</File>
<File
RelativePath="..\..\include\whohas.h"
>
</File>
<File
RelativePath="..\..\include\whois.h"
>
</File>
<File
RelativePath="..\..\include\wp.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\..\src\abort.c"
>
</File>
<File
RelativePath="..\..\src\address.c"
>
</File>
<File
RelativePath="..\object\ai.c"
>
</File>
<File
RelativePath="..\..\src\alarm_ack.c"
>
</File>
<File
RelativePath="..\object\ao.c"
>
</File>
<File
RelativePath="..\..\src\apdu.c"
>
</File>
<File
RelativePath="..\..\src\arf.c"
>
</File>
<File
RelativePath="..\object\av.c"
>
</File>
<File
RelativePath="..\..\src\awf.c"
>
</File>
<File
RelativePath="..\..\src\bacaddr.c"
>
</File>
<File
RelativePath="..\..\src\bacapp.c"
>
</File>
<File
RelativePath="..\..\src\bacdcode.c"
>
</File>
<File
RelativePath="..\..\src\bacdevobjpropref.c"
>
</File>
<File
RelativePath="..\..\src\bacerror.c"
>
</File>
<File
RelativePath="..\object\bacfile.c"
>
</File>
<File
RelativePath="..\..\src\bacint.c"
>
</File>
<File
RelativePath="..\..\src\bacprop.c"
>
</File>
<File
RelativePath="..\..\src\bacpropstates.c"
>
</File>
<File
RelativePath="..\..\src\bacreal.c"
>
</File>
<File
RelativePath="..\..\src\bacstr.c"
>
</File>
<File
RelativePath="..\..\src\bactext.c"
>
</File>
<File
RelativePath="..\object\bi.c"
>
</File>
<File
RelativePath="..\..\src\bigend.c"
>
</File>
<File
RelativePath="..\..\ports\win32\bip-init.c"
>
</File>
<File
RelativePath="..\..\src\bip.c"
>
</File>
<File
RelativePath="..\object\bo.c"
>
</File>
<File
RelativePath="..\object\bv.c"
>
</File>
<File
RelativePath="..\..\src\bvlc.c"
>
</File>
<File
RelativePath="..\..\src\cov.c"
>
</File>
<File
RelativePath="..\..\src\crc.c"
>
</File>
<File
RelativePath="..\..\src\datalink.c"
>
</File>
<File
RelativePath="..\..\src\datetime.c"
>
</File>
<File
RelativePath="..\..\src\dcc.c"
>
</File>
<File
RelativePath="..\..\src\debug.c"
>
</File>
<File
RelativePath="..\object\device.c"
>
</File>
<File
RelativePath="..\handler\dlenv.c"
>
</File>
<File
RelativePath="..\..\ports\win32\dlmstp.c"
>
</File>
<File
RelativePath="..\..\src\event.c"
>
</File>
<File
RelativePath="..\..\src\fifo.c"
>
</File>
<File
RelativePath="..\..\src\filename.c"
>
</File>
<File
RelativePath="..\handler\h_alarm_ack.c"
>
</File>
<File
RelativePath="..\handler\h_arf.c"
>
</File>
<File
RelativePath="..\handler\h_arf_a.c"
>
</File>
<File
RelativePath="..\handler\h_awf.c"
>
</File>
<File
RelativePath="..\handler\h_cov.c"
>
</File>
<File
RelativePath="..\handler\h_dcc.c"
>
</File>
<File
RelativePath="..\handler\h_iam.c"
>
</File>
<File
RelativePath="..\handler\h_ihave.c"
>
</File>
<File
RelativePath="..\handler\h_lso.c"
>
</File>
<File
RelativePath="..\handler\h_npdu.c"
>
</File>
<File
RelativePath="..\handler\h_pt.c"
>
</File>
<File
RelativePath="..\handler\h_pt_a.c"
>
</File>
<File
RelativePath="..\handler\h_rd.c"
>
</File>
<File
RelativePath="..\handler\h_rp.c"
>
</File>
<File
RelativePath="..\handler\h_rp_a.c"
>
</File>
<File
RelativePath="..\handler\h_rpm.c"
>
</File>
<File
RelativePath="..\handler\h_rpm_a.c"
>
</File>
<File
RelativePath="..\handler\h_ts.c"
>
</File>
<File
RelativePath="..\handler\h_ucov.c"
>
</File>
<File
RelativePath="..\handler\h_whohas.c"
>
</File>
<File
RelativePath="..\handler\h_whois.c"
>
</File>
<File
RelativePath="..\handler\h_wp.c"
>
</File>
<File
RelativePath="..\..\src\iam.c"
>
</File>
<File
RelativePath="..\..\src\ihave.c"
>
</File>
<File
RelativePath="..\..\src\indtext.c"
>
</File>
<File
RelativePath="..\..\src\key.c"
>
</File>
<File
RelativePath="..\..\src\keylist.c"
>
</File>
<File
RelativePath="..\object\lc.c"
>
</File>
<File
RelativePath="..\object\lo.c"
>
</File>
<File
RelativePath="..\..\src\lso.c"
>
</File>
<File
RelativePath="..\object\lsp.c"
>
</File>
<File
RelativePath=".\main.c"
>
</File>
<File
RelativePath="..\..\src\memcopy.c"
>
</File>
<File
RelativePath="..\object\mso.c"
>
</File>
<File
RelativePath="..\..\src\mstp.c"
>
</File>
<File
RelativePath="..\..\src\mstptext.c"
>
</File>
<File
RelativePath="..\handler\noserv.c"
>
</File>
<File
RelativePath="..\..\src\npdu.c"
>
</File>
<File
RelativePath="..\handler\objects.c"
>
</File>
<File
RelativePath="..\..\src\ptransfer.c"
>
</File>
<File
RelativePath="..\..\src\rd.c"
>
</File>
<File
RelativePath="..\..\src\reject.c"
>
</File>
<File
RelativePath="..\..\src\ringbuf.c"
>
</File>
<File
RelativePath="..\..\src\rp.c"
>
</File>
<File
RelativePath="..\..\src\rpm.c"
>
</File>
<File
RelativePath="..\..\ports\win32\rs485.c"
>
</File>
<File
RelativePath="..\handler\s_ack_alarm.c"
>
</File>
<File
RelativePath="..\handler\s_arfs.c"
>
</File>
<File
RelativePath="..\handler\s_awfs.c"
>
</File>
<File
RelativePath="..\handler\s_cov.c"
>
</File>
<File
RelativePath="..\handler\s_dcc.c"
>
</File>
<File
RelativePath="..\handler\s_iam.c"
>
</File>
<File
RelativePath="..\handler\s_ihave.c"
>
</File>
<File
RelativePath="..\handler\s_lso.c"
>
</File>
<File
RelativePath="..\handler\s_ptransfer.c"
>
</File>
<File
RelativePath="..\handler\s_rd.c"
>
</File>
<File
RelativePath="..\handler\s_router.c"
>
</File>
<File
RelativePath="..\handler\s_rp.c"
>
</File>
<File
RelativePath="..\handler\s_rpm.c"
>
</File>
<File
RelativePath="..\handler\s_ts.c"
>
</File>
<File
RelativePath="..\handler\s_uevent.c"
>
</File>
<File
RelativePath="..\handler\s_whohas.c"
>
</File>
<File
RelativePath="..\handler\s_whois.c"
>
</File>
<File
RelativePath="..\handler\s_wp.c"
>
</File>
<File
RelativePath="..\..\src\sbuf.c"
>
</File>
<File
RelativePath="..\..\src\timestamp.c"
>
</File>
<File
RelativePath="..\..\src\timesync.c"
>
</File>
<File
RelativePath="..\..\src\tsm.c"
>
</File>
<File
RelativePath="..\handler\txbuf.c"
>
</File>
<File
RelativePath="..\..\src\version.c"
>
</File>
<File
RelativePath="..\..\src\whohas.c"
>
</File>
<File
RelativePath="..\..\src\whois.c"
>
</File>
<File
RelativePath="..\..\src\wp.c"
>
</File>
</Filter>
<File
RelativePath=".\debug\BuildLog.htm"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
+2
View File
@@ -73,6 +73,8 @@ Makefile = svn:eol-style=native
*.java = svn:mime-type=text/plain;svn:eol-style=native
*.properties = svn:mime-type=text/plain;svn:eol-style=native
*.sql = svn:mime-type=text/plain;svn:eol-style=native
*.sln = svn:eol-style=CRLF
*.vcproj = svn:eol-style=CRLF
To test the properties of a file:
$ svn proplist
+12 -1
View File
@@ -200,7 +200,18 @@ extern "C" {
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_conf_private_trans(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_conf_private_trans_ack(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
#
#ifdef __cplusplus
}
#endif /* __cplusplus */
+24
View File
@@ -0,0 +1,24 @@
/* Sample data structure for confirmed private transfer
We have a simple data structure which can be written to
and read from by sending a confirmed private transfer
request with the appropriate parameters.
*/
#define MY_MAX_STR 32
#define MY_MAX_BLOCK 8
#define MY_SVC_READ 0
#define MY_SVC_WRITE 1
#define MY_ERR_OK 0
#define MY_ERR_BAD_INDEX 1
typedef struct MyData {
uint8_t cMyByte1;
uint8_t cMyByte2;
float fMyReal;
int8_t sMyString[MY_MAX_STR+1]; // A little extra for the nul
} DATABLOCK;
+4
View File
@@ -65,6 +65,7 @@ CORE3_SRC = $(BACNET_CORE)\arf.c \
$(BACNET_CORE)\dcc.c \
$(BACNET_CORE)\iam.c \
$(BACNET_CORE)\ihave.c \
$(BACNET_CORE)\ptransfer.c \
$(BACNET_CORE)\rd.c \
$(BACNET_CORE)\rp.c \
$(BACNET_CORE)\rpm.c \
@@ -109,6 +110,9 @@ HANDLER_SRC = \
$(BACNET_HANDLER)\s_uevent.c \
$(BACNET_HANDLER)\s_whohas.c \
$(BACNET_HANDLER)\s_whois.c \
$(BACNET_HANDLER)\s_ptransfer.c \
$(BACNET_HANDLER)\h_pt.c \
$(BACNET_HANDLER)\h_pt_a.c \
$(BACNET_HANDLER)\s_wp.c
OBJECT_SRC = $(BACNET_OBJECT)\device.c \
+27 -10
View File
@@ -453,16 +453,33 @@ void apdu_handler(
invoke_id = apdu[1];
service_choice = apdu[2];
len = 3;
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
/* FIXME: we could validate that the tag is enumerated... */
len += decode_enumerated(&apdu[len], len_value, &error_class);
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
/* FIXME: we could validate that the tag is enumerated... */
len += decode_enumerated(&apdu[len], len_value, &error_code);
/* FIXME: Currently special case for C_P_T but there are others which may
need consideration such as ChangeList-Error, CreateObject-Error,
WritePropertyMultiple-Error and VTClose_Error but they may be left as
is for now until support for these services is added */
if(service_choice = SERVICE_CONFIRMED_PRIVATE_TRANSFER) { /* skip over opening tag 0 */
if (decode_is_opening_tag_number(&apdu[len], 0)) {
len++; /* a tag number of 0 is not extended so only one octet */
}
}
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
/* FIXME: we could validate that the tag is enumerated... */
len += decode_enumerated(&apdu[len], len_value, &error_class);
len +=
decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
/* FIXME: we could validate that the tag is enumerated... */
len += decode_enumerated(&apdu[len], len_value, &error_code);
if(service_choice = SERVICE_CONFIRMED_PRIVATE_TRANSFER) { /* skip over closing tag 0 */
if (decode_is_closing_tag_number(&apdu[len], 0)) {
len++; /* a tag number of 0 is not extended so only one octet */
}
}
if (service_choice < MAX_BACNET_CONFIRMED_SERVICE) {
if (Error_Function[service_choice])
Error_Function[service_choice] (src, invoke_id,
+1
View File
@@ -35,6 +35,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h> /* for strlen */
#include "config.h"
#include "bacstr.h"
#include "bits.h"