Skip to content

Commit

Permalink
Merge pull request #13 from chipkin/update_stack_v5x
Browse files Browse the repository at this point in the history
Update stack v5x
  • Loading branch information
ssmethurst authored Oct 31, 2024
2 parents b7d503c + 9fa039d commit 7d815da
Show file tree
Hide file tree
Showing 10 changed files with 1,590 additions and 1,582 deletions.
106 changes: 0 additions & 106 deletions .gitlab-ci.yml

This file was deleted.

3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

135 changes: 116 additions & 19 deletions BACnetClientExample/BACnetClientExample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ uint8_t invokeId;

// Constants
// =======================================
const std::string APPLICATION_VERSION = "0.0.9"; // See CHANGELOG.md for a full list of changes.
const std::string APPLICATION_VERSION = "1.0.0"; // See CHANGELOG.md for a full list of changes.
const uint32_t MAX_XML_RENDER_BUFFER_LENGTH = 1024 * 20;

// Settings
Expand All @@ -71,6 +71,7 @@ const uint32_t SETTING_CLIENT_DEVICE_INSTANCE = 389002;
const uint16_t SETTING_DOWNSTREAM_DEVICE_PORT = SETTING_BACNET_IP_PORT;
const uint32_t SETTING_DOWNSTREAM_DEVICE_INSTANCE = 389999;
const std::string SETTING_DEFAULT_DOWNSTREAM_DEVICE_IP_ADDRESS = "192.168.2.217";
const std::string SETTING_DEFAULT_DEVICE_PASSWORD = "12345";

// Downstream IP Initialization
// =======================================
Expand All @@ -79,7 +80,7 @@ std::string downstream_Device_ip_address;

// Callback Functions to Register to the DLL
// Message Functions
uint16_t CallbackReceiveMessage(uint8_t* message, const uint16_t maxMessageLength, uint8_t* receivedConnectionString, const uint8_t maxConnectionStringLength, uint8_t* receivedConnectionStringLength, uint8_t* networkType);
uint16_t CallbackReceiveMessage(uint8_t* message, const uint16_t maxMessageLength, uint8_t* sourceConnectionString, uint8_t* sourceConnectionStringLength, uint8_t* destinationConnectionString, uint8_t* destinationConnectionStringLength, const uint8_t maxConnectionStringLength, uint8_t* networkType);
uint16_t CallbackSendMessage(const uint8_t* message, const uint16_t messageLength, const uint8_t* connectionString, const uint8_t connectionStringLength, const uint8_t networkType, bool broadcast);

// System Functions
Expand Down Expand Up @@ -126,7 +127,11 @@ void ExampleWhoIs();
void ExampleReadProperty();
void ExampleWriteProperty();
void ExampleSubscribeCOV();
void ExampleSubscribeCOVProperty();
void ExampleConfirmedTextMessage();
void ExampleTimeSynchronizationMessage();
void ExampleReinitializeDevice();
void ExampleDeviceCommunicationControl(bool enable);

int main(int argc, char ** argv )
{
Expand Down Expand Up @@ -242,7 +247,7 @@ int main(int argc, char ** argv )
std::cout << "FYI: Entering main loop..." << std::endl;
for (;;) {
// Call the DLLs loop function which checks for messages and processes them.
fpLoop();
fpTick();

// Handle any user input.
if (!DoUserInput()) {
Expand Down Expand Up @@ -287,14 +292,35 @@ bool DoUserInput()
ExampleWriteProperty();
break;
}
case 'c': {
case 's': {
ExampleSubscribeCOV();
break;
}
case 't': {
case 'p': {
ExampleSubscribeCOVProperty();
break;
}
case 'm': {
ExampleConfirmedTextMessage();
break;
}
case 't': {
ExampleTimeSynchronizationMessage();
break;
}
case 'i': {
ExampleReinitializeDevice();
break;
}
case 'd': {
ExampleDeviceCommunicationControl(false);
break;
}
case 'e': {
ExampleDeviceCommunicationControl(true);
break;
}
case 'h':
default: {
// Print the Help
std::cout << std::endl << std::endl;
Expand All @@ -305,12 +331,18 @@ bool DoUserInput()
std::cout << "Example: BACnetClient 192.168.1.126" << std::endl << std::endl;

std::cout << "Help: " << std::endl;
std::cout << "- Q - Quit" << std::endl;
std::cout << "- W - Send WhoIs message" << std::endl;
std::cout << "- R - Send Read property messages" << std::endl;
std::cout << "- U - Send Write property messages" << std::endl;
std::cout << "- C - Send Subscribe COV Request" << std::endl;
std::cout << "- T - Send Confirmed Text Message Request" << std::endl;
std::cout << "- R - Send ReadProperty messages" << std::endl;
std::cout << "- U - Send WriteProperty messages" << std::endl;
std::cout << "- S - Send SubscribeCOV Request" << std::endl;
std::cout << "- P - Send SubscribeCOVProperty Request" << std::endl;
std::cout << "- M - Send ConfirmedTextMessage Request" << std::endl;
std::cout << "- T - Send TimeSynchronization Request" << std::endl;
std::cout << "- R - Send ReinitializedDevice Request" << std::endl;
std::cout << "- D - Send DeviceCommunicationControl Request to Disable" << std::endl;
std::cout << "- E - Send DeviceCommunicationControl Request to Enable" << std::endl;
std::cout << "- H - Display Help information" << std::endl;
std::cout << "- Q - Quit" << std::endl;
std::cout << std::endl;
break;
}
Expand All @@ -325,7 +357,7 @@ bool DoUserInput()
void WaitForResponse(unsigned int timeout /*=3*/) {
time_t expireTime = time(0) + timeout;
while (time(0) < expireTime) {
fpLoop();
fpTick();
}
}

Expand Down Expand Up @@ -437,7 +469,7 @@ void ExampleSubscribeCOV() {

// Subscribe to the analog input and analog value objects in the server example

std::cout << "Sending Subscribe COV Request. Analog Input, INSTANCE=[0], timeToLive = " << timeToLive << ", processIdentifier = " << analogValueProcessIdentifier << std::endl;
std::cout << "Sending Subscribe COV Request. Analog Input, INSTANCE=[0], timeToLive = " << timeToLive << ", processIdentifier = " << analogInputProcessIdentifier << std::endl;
fpSendSubscribeCOV(&invokeId, analogInputProcessIdentifier, CASBACnetStackExampleConstants::OBJECT_TYPE_ANALOG_INPUT, 0, false, timeToLive, downstreamConnectionString, 6, 0, 0, NULL, 0);

WaitForResponse();
Expand All @@ -448,6 +480,18 @@ void ExampleSubscribeCOV() {
WaitForResponse();
}

void ExampleSubscribeCOVProperty() {
const uint16_t timeToLive = 60 * 5; // 5 Min subscription time

// Local process identifier, must be unique for each subscribe COV request
const uint16_t analogValueProcessIdentifier = 0;

// Subscribe to the analog input and analog value objects in the server example

std::cout << "Sending Subscribe COV Property Request. Analog Value, INSTANCE=[2], timeToLive = " << timeToLive << ", processIdentifier = " << analogValueProcessIdentifier << std::endl;
fpSendSubscribeCOVProperty(&invokeId, analogValueProcessIdentifier, CASBACnetStackExampleConstants::OBJECT_TYPE_ANALOG_VALUE, 2, CASBACnetStackExampleConstants::PROPERTY_IDENTIFIER_PRESENT_VALUE, false, 0, true, 5.0f, false, timeToLive, downstreamConnectionString, 6, 0, 0, NULL, 0);
}

void ExampleConfirmedTextMessage() {
// Text message settings
bool useMessageClass = true; // Enable or disable message class property
Expand All @@ -464,21 +508,74 @@ void ExampleConfirmedTextMessage() {
WaitForResponse();
}

void ExampleTimeSynchronizationMessage() {
// Time Synchronization Settings
uint8_t year = 2024 - 1900;
uint8_t month = 8;
uint8_t day = 15;
uint8_t weekday = 3;
uint8_t hour = 8;
uint8_t minute = 8;
uint8_t seconds = 8;
uint8_t hundrethSeconds = 0;

// Send TimeSynchronization request
// C++ server example configured to handle
std::cout << "Sending TimeSynchronization Message";
fpSendTimeSynchronization(year, month, day, weekday, hour, minute, seconds, hundrethSeconds, downstreamConnectionString, 6, 0, false, 0, NULL, 0);

WaitForResponse();
// Note: TimeSynchronization is an unconfirmed request, which means the downstream device will not response.
// The WaitForResponse is called here just to wait for some cycles before continuing.

// Send UtcTimeSynchronization request
// C++ server example configured to handle
std::cout << "Sending UTCTimeSynchronization Message";
fpSendUTCTimeSynchronization(year, month, day, weekday, hour, minute, seconds, hundrethSeconds, downstreamConnectionString, 6, 0, false, 0, NULL, 0);

WaitForResponse();
}

void ExampleReinitializeDevice() {
// ReinitializeDevice Settings
uint8_t reinitializedState = CASBACnetStackExampleConstants::REINITIALIZED_STATE_ACTIVATE_CHANGES;

// Send ReinitializeDevice request
// C++ server example configured to handle
std::cout << "Sending ReinitializeDevice Message to activate changes";
fpSendReinitializeDevice(&invokeId, reinitializedState, SETTING_DEFAULT_DEVICE_PASSWORD.c_str(), SETTING_DEFAULT_DEVICE_PASSWORD.length(), downstreamConnectionString, 6, 0, 0, NULL, 0);
}

void ExampleDeviceCommunicationControl(bool enable) {
if (enable) {
// Send DeviceCommunicationControl request
// C++ server example configured to handle
std::cout << "Sending DeviceCommunicationControl Message to enable BACnet communication";
fpSendDeviceCommunicationControl(&invokeId, CASBACnetStackExampleConstants::ENABLEDISABLE_ENABLE, false, 0, SETTING_DEFAULT_DEVICE_PASSWORD.c_str(), SETTING_DEFAULT_DEVICE_PASSWORD.length(), downstreamConnectionString, 6, 0, 0, NULL, 0);
}
else {
// Send DeviceCommunicationControl request
// C++ server example configured to handle
std::cout << "Sending DeviceCommunicationControl Message to disable BACnet communication";
fpSendDeviceCommunicationControl(&invokeId, CASBACnetStackExampleConstants::ENABLEDISABLE_DISABLE, false, 0, SETTING_DEFAULT_DEVICE_PASSWORD.c_str(), SETTING_DEFAULT_DEVICE_PASSWORD.length(), downstreamConnectionString, 6, 0, 0, NULL, 0);
}
}


// ================================================================================================
// Callbacks
// ================================================================================================


// Callback used by the BACnet Stack to check if there is a message to process
uint16_t CallbackReceiveMessage(uint8_t* message, const uint16_t maxMessageLength, uint8_t* receivedConnectionString, const uint8_t maxConnectionStringLength, uint8_t* receivedConnectionStringLength, uint8_t* networkType)
uint16_t CallbackReceiveMessage(uint8_t* message, const uint16_t maxMessageLength, uint8_t* sourceConnectionString, uint8_t* sourceConnectionStringLength, uint8_t* destinationConnectionString, uint8_t* destinationConnectionStringLength, const uint8_t maxConnectionStringLength, uint8_t* networkType)
{
// Check parameters
if (message == NULL || maxMessageLength == 0) {
std::cerr << "Invalid input buffer" << std::endl;
return 0;
}
if (receivedConnectionString == NULL || maxConnectionStringLength == 0) {
if (sourceConnectionString == NULL || maxConnectionStringLength == 0) {
std::cerr << "Invalid connection string buffer" << std::endl;
return 0;
}
Expand All @@ -497,14 +594,14 @@ uint16_t CallbackReceiveMessage(uint8_t* message, const uint16_t maxMessageLengt
std::cout << "FYI: Received message from [" << ipAddress << ":" << port << "], length [" << bytesRead << "]" << std::endl;

// Convert the IP Address to the connection string
if (!ChipkinCommon::ChipkinConvert::IPAddressToBytes(ipAddress, receivedConnectionString, maxConnectionStringLength)) {
if (!ChipkinCommon::ChipkinConvert::IPAddressToBytes(ipAddress, sourceConnectionString, maxConnectionStringLength)) {
std::cerr << "Failed to convert the ip address into a connectionString" << std::endl;
return 0;
}
receivedConnectionString[4] = port / 256;
receivedConnectionString[5] = port % 256;
sourceConnectionString[4] = port / 256;
sourceConnectionString[5] = port % 256;

*receivedConnectionStringLength = 6;
*sourceConnectionStringLength = 6;
*networkType = CASBACnetStackExampleConstants::NETWORK_TYPE_IP;

// Process the message as XML
Expand Down Expand Up @@ -568,7 +665,7 @@ uint16_t CallbackSendMessage(const uint8_t* message, const uint16_t messageLengt

// Get the XML rendered version of the just sent message
static char xmlRenderBuffer[MAX_XML_RENDER_BUFFER_LENGTH];
if (fpDecodeAsXML((char*)message, messageLength, xmlRenderBuffer, MAX_XML_RENDER_BUFFER_LENGTH, networkType) > 0) {
if (fpDecodeAsXML((char*)message, messageLength, xmlRenderBuffer, MAX_XML_RENDER_BUFFER_LENGTH, CASBACnetStackExampleConstants::NETWORK_TYPE_IP) > 0) {
std::cout << xmlRenderBuffer << std::endl << std::endl;
memset(xmlRenderBuffer, 0, MAX_XML_RENDER_BUFFER_LENGTH);
}
Expand Down
Loading

0 comments on commit 7d815da

Please sign in to comment.