diff --git a/bacnet-stack/cov.c b/bacnet-stack/cov.c index d538ff0a..dab5c96c 100644 --- a/bacnet-stack/cov.c +++ b/bacnet-stack/cov.c @@ -355,7 +355,7 @@ void testCOV(Test * pTest) } #ifdef TEST_COV -int main(void) +int main(int argc, char *argv[]) { Test *pTest; bool rc; diff --git a/bacnet-stack/demo/ucov/Makefile b/bacnet-stack/demo/ucov/Makefile new file mode 100644 index 00000000..068801ad --- /dev/null +++ b/bacnet-stack/demo/ucov/Makefile @@ -0,0 +1,79 @@ +#Makefile to build BACnet Application for the Linux Port +CC = gcc +BASEDIR = . +#CFLAGS = -Wall -I. +# -g for debugging with gdb +#CFLAGS = -Wall -I. -O2 -g +# Note: you can strip out symbols using the strip command +# to get an idea of how big the compile really is. +#DEFINES = -DBACFILE=1 -DBACDL_ETHERNET=1 +#DEFINES = -DBACFILE=1 -DBACDL_ARCNET=1 +#DEFINES = -DBACFILE=1 -DBACDL_MSTP=1 +DEFINES = -DBACFILE=1 -DTSM_ENABLED=0 -DBACDL_BIP=1 +BACNET_PORT = ../../ports/linux +BACNET_OBJECT = ../object +BACNET_HANDLER = ../handler +BACNET_ROOT = ../.. +INCLUDES = -I$(BACNET_ROOT) -I$(BACNET_PORT) -I$(BACNET_OBJECT) -I$(BACNET_HANDLER) + +CFLAGS = -Wall -g $(INCLUDES) $(DEFINES) + +TARGET = bacucov + +SRCS = main.c \ + $(BACNET_PORT)/bip-init.c \ + $(BACNET_ROOT)/bip.c \ + $(BACNET_HANDLER)/txbuf.c \ + $(BACNET_HANDLER)/noserv.c \ + $(BACNET_HANDLER)/h_whois.c \ + $(BACNET_HANDLER)/h_rp.c \ + $(BACNET_HANDLER)/h_iam.c \ + $(BACNET_OBJECT)/device.c \ + $(BACNET_OBJECT)/ai.c \ + $(BACNET_OBJECT)/ao.c \ + $(BACNET_OBJECT)/bi.c \ + $(BACNET_OBJECT)/bo.c \ + $(BACNET_OBJECT)/lsp.c \ + $(BACNET_OBJECT)/bacfile.c \ + $(BACNET_ROOT)/filename.c \ + $(BACNET_ROOT)/rp.c \ + $(BACNET_ROOT)/wp.c \ + $(BACNET_ROOT)/bacdcode.c \ + $(BACNET_ROOT)/bacapp.c \ + $(BACNET_ROOT)/bacprop.c \ + $(BACNET_ROOT)/bacstr.c \ + $(BACNET_ROOT)/bactext.c \ + $(BACNET_ROOT)/indtext.c \ + $(BACNET_ROOT)/bigend.c \ + $(BACNET_ROOT)/whois.c \ + $(BACNET_ROOT)/iam.c \ + $(BACNET_ROOT)/datalink.c \ + $(BACNET_ROOT)/address.c \ + $(BACNET_ROOT)/arf.c \ + $(BACNET_ROOT)/cov.c \ + $(BACNET_ROOT)/dcc.c \ + $(BACNET_ROOT)/abort.c \ + $(BACNET_ROOT)/reject.c \ + $(BACNET_ROOT)/bacerror.c \ + $(BACNET_ROOT)/apdu.c \ + $(BACNET_ROOT)/npdu.c + +OBJS = ${SRCS:.c=.o} + +all: ${TARGET} + +${TARGET}: ${OBJS} + ${CC} -o $@ ${OBJS} + +.c.o: + ${CC} -c ${CFLAGS} $*.c -o $@ + +depend: + rm -f .depend + ${CC} -MM ${CFLAGS} *.c >> .depend + +clean: + rm -rf core ${TARGET} $(OBJS) *.bak ports/linux/*.bak *.1 *.ini + +include: .depend + diff --git a/bacnet-stack/demo/ucov/main.c b/bacnet-stack/demo/ucov/main.c new file mode 100644 index 00000000..d129867f --- /dev/null +++ b/bacnet-stack/demo/ucov/main.c @@ -0,0 +1,218 @@ +/************************************************************************** +* +* Copyright (C) 2006 Steve Karg +* +* 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 */ +#include +#include +#include +#include +#include /* for time */ +#include +#include "bactext.h" +#include "iam.h" +#include "cov.h" +#include "tsm.h" +#include "address.h" +#include "config.h" +#include "bacdef.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" + +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); +} + +int main(int argc, char *argv[]) +{ + char *value_string = NULL; + bool status = false; + BACNET_COV_DATA cov_data; + uint8_t tag; + + if (argc < 7) { + /* note: priority 16 and 0 should produce the same end results... */ + printf("Usage: %s pid device-id object-type object-instance " + "time property tag value [priority] [index]\r\n" + "\r\n" + "pid:\r\n" + "Process Identifier for this broadcast.\r\n" + "\r\n" + "device-id:\r\n" + "The Initiating BACnet Device Object Instance number.\r\n" + "\r\n" + "object-type:\r\n" + "The monitored object type is the integer value of the\r\n" + "enumeration BACNET_OBJECT_TYPE in bacenum.h. For example,\r\n" + "if you were monitoring Analog Output 2, the object-type\r\n" + "would be 1.\r\n" + "\r\n" + "object-instance:\r\n" + "The monitored object instance number.\r\n" + "\r\n" + "time:\r\n" + "The subscription time remaining is conveyed in seconds.\r\n" + "\r\n" + "property:\r\n" + "The property is an integer value of the enumeration \r\n" + "BACNET_PROPERTY_ID in bacenum.h. For example, if you were\r\n" + "monitoring the Present Value property, you would use 85\r\n" + "as the property.\r\n" + "\r\n" + "tag:\r\n" + "Tag is the integer value of the enumeration BACNET_APPLICATION_TAG \r\n" + "in bacenum.h. It is the data type of the value that you are\r\n" + "monitoring. For example, if you were monitoring a REAL value, you would \r\n" + "use a tag of 4." + "\r\n" + "value:\r\n" + "The value is an ASCII representation of some type of data that you\r\n" + "are monitoring. It is encoded using the tag information provided. For\r\n" + "example, if you were writing a REAL value of 100.0, you would use \r\n" + "100.0 as the value.\r\n" + "\r\n" + "[priority]:\r\n" + "This optional parameter is used for reporting the priority of the\r\n" + "value. If no priority is given, none is sent, and the BACnet \r\n" + "standard requires that the value is reported at the lowest \r\n" + "priority (16) if the object property supports priorities.\r\n" + "\r\n" + "[index]\r\n" + "This optional integer parameter is the index number of an array.\r\n" + "If the property is an array, individual elements can be reported.\r\n" + "\r\n" + "Here is a brief overview of BACnet property and tags:\r\n" + "Certain properties are expected to be written with certain \r\n" + "application tags, so you probably need to know which ones to use\r\n" + "with each property of each object. It is almost safe to say that\r\n" + "given a property and an object and a table, the tag could be looked\r\n" + "up automatically. There may be a few exceptions to this, such as\r\n" + "the Any property type in the schedule object and the Present Value\r\n" + "accepting REAL, BOOLEAN, NULL, etc. Perhaps it would be simpler for\r\n" + "the demo to use this kind of table - but I also wanted to be able\r\n" + "to do negative testing by passing the wrong tag and have the server\r\n" + "return a reject message.\r\n" + "\r\n" + "Example:\r\n" + "If you want generate an unconfirmed COV,\r\n" + "you could send the following command:\r\n" + "%s 1 2 3 4 5 85 4 100.0\r\n" + "where 1=pid, 2=device-id, 3=AV, 4=object-id, 5=time,\r\n" + "85=Present-Value, 4=REAL, 100.0=value\r\n", + 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); + 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); + cov_data.timeRemaining = strtol(argv[5], NULL, 0); + cov_data.listOfValues.propertyIdentifier = strtol(argv[6], NULL, 0); + tag = strtol(argv[7], NULL, 0); + value_string = argv[8]; + /* optional priority */ + if (argc > 9) + cov_data.listOfValues.priority = strtol(argv[9], NULL, 0); + else + cov_data.listOfValues.priority = BACNET_NO_PRIORITY; + /* optional index */ + if (argc > 10) + cov_data.listOfValues.propertyArrayIndex = strtol(argv[10], NULL, 0); + else + cov_data.listOfValues.propertyArrayIndex = BACNET_ARRAY_ALL; + + if (cov_data.initiatingDeviceIdentifier >= BACNET_MAX_INSTANCE) { + fprintf(stderr, "device-instance=%u - it must be less than %u\r\n", + cov_data.initiatingDeviceIdentifier, BACNET_MAX_INSTANCE); + return 1; + } + if (cov_data.monitoredObjectIdentifier.type > MAX_BACNET_OBJECT_TYPE) { + fprintf(stderr, "object-type=%u - it must be less than %u\r\n", + cov_data.monitoredObjectIdentifier.type, MAX_BACNET_OBJECT_TYPE + 1); + return 1; + } + if (cov_data.monitoredObjectIdentifier.instance > BACNET_MAX_INSTANCE) { + fprintf(stderr, "object-instance=%u - it must be less than %u\r\n", + cov_data.monitoredObjectIdentifier.instance, BACNET_MAX_INSTANCE + 1); + return 1; + } + if (cov_data.listOfValues.propertyIdentifier > MAX_BACNET_PROPERTY_ID) { + fprintf(stderr, "object-type=%u - it must be less than %u\r\n", + cov_data.listOfValues.propertyIdentifier, MAX_BACNET_PROPERTY_ID + 1); + return 1; + } + if (tag >= MAX_BACNET_APPLICATION_TAG) { + fprintf(stderr, "tag=%u - it must be less than %u\r\n", + tag, MAX_BACNET_APPLICATION_TAG); + return 1; + } + status = bacapp_parse_application_data(tag, + value_string, &cov_data.listOfValues.value); + if (!status) { + /* FIXME: show the expected entry format for the tag */ + fprintf(stderr, "unable to parse the tag value\r\n"); + return 1; + } + + /* setup my info */ + Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); + Init_Service_Handlers(); + /* configure standard BACnet/IP port */ + bip_set_interface("eth0"); /* for linux */ + bip_set_port(0xBAC0); + if (!bip_init()) + return 1; + + /* only one value in our value list */ + cov_data.listOfValues.next = NULL; + + cov_send(&Handler_Transmit_Buffer[0],&cov_data); + + return 0; +} diff --git a/bacnet-stack/demo/ucov/makefile.b32 b/bacnet-stack/demo/ucov/makefile.b32 new file mode 100644 index 00000000..3f365309 --- /dev/null +++ b/bacnet-stack/demo/ucov/makefile.b32 @@ -0,0 +1,147 @@ +# +# 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 = bacucov +PRODUCT_EXE = $(PRODUCT).exe + +# Choose the Data Link Layer to Enable +DEFINES = -DBACDL_BIP=1;TSM_ENABLED=0 + +SRCS = main.c \ + ..\..\ports\win32\bip-init.c \ + ..\..\filename.c \ + ..\..\bip.c \ + ..\..\demo\handler\txbuf.c \ + ..\..\demo\handler\noserv.c \ + ..\..\demo\handler\h_whois.c \ + ..\..\demo\handler\h_iam.c \ + ..\..\demo\handler\h_rp.c \ + ..\..\bacdcode.c \ + ..\..\bacapp.c \ + ..\..\bacstr.c \ + ..\..\bactext.c \ + ..\..\indtext.c \ + ..\..\bigend.c \ + ..\..\whois.c \ + ..\..\iam.c \ + ..\..\rp.c \ + ..\..\wp.c \ + ..\..\arf.c \ + ..\..\awf.c \ + ..\..\cov.c \ + ..\..\dcc.c \ + ..\..\demo\object\bacfile.c \ + ..\..\demo\object\device.c \ + ..\..\demo\object\ai.c \ + ..\..\demo\object\ao.c \ + ..\..\demo\object\bi.c \ + ..\..\demo\object\bo.c \ + ..\..\demo\object\lsp.c \ + ..\..\datalink.c \ + ..\..\address.c \ + ..\..\abort.c \ + ..\..\reject.c \ + ..\..\bacerror.c \ + ..\..\apdu.c \ + ..\..\npdu.c + +OBJS = $(SRCS:.c=.obj) + +# Compiler definitions +# +CC = $(BORLAND_DIR)\bin\bcc32 +bcc32.cfg +#LINK = $(BORLAND_DIR)\bin\tlink32 +LINK = $(BORLAND_DIR)\bin\ilink32 +TLIB = $(BORLAND_DIR)\bin\tlib + +# +# Include directories +# +CC_DIR = $(BORLAND_DIR)\BIN +INCL_DIRS = -I$(BORLAND_DIR)\include;..\..\;..\..\demo\object\;..\..\demo\handler\;..\..\ports\win32\;. + +CFLAGS = $(INCL_DIRS) $(CS_FLAGS) $(DEFINES) + +# Libraries +# +C_LIB_DIR = $(BORLAND_DIR)\lib + +LIBS = $(C_LIB_DIR)\IMPORT32.lib \ +$(C_LIB_DIR)\CW32MT.lib + +# +# Main target +# +# This should be the first one in the makefile + +all : bcc32.cfg $(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 +$(PRODUCT_EXE) : $(OBJS) + @echo Running Linker for $(PRODUCT_EXE) + $(LINK) -L$(C_LIB_DIR) -m -c -s -v @&&| # temp response file, starts with | + $(BORLAND_DIR)\lib\c0x32.obj $** # $** lists each dependency + $< + $*.map + $(LIBS) +| # end of temp response file + +# +# Utilities + +clean : + @echo Deleting obj files, $(PRODUCT_EXE) and map files. +# del $(OBJS) # command too long, bummer! + del *.obj + del ..\..\*.obj + del ..\..\demo\handler\*.obj + del ..\..\demo\object\*.obj + del ..\..\ports\win32\*.obj + del $(PRODUCT_EXE) + del *.map + del bcc32.cfg + +# +# Generic rules +# +.SUFFIXES: .cpp .c .sbr .obj + +# +# cc generic rule +# +.c.obj: + $(CC) -o$@ $< + +# Compiler configuration file +bcc32.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