Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
variables:
GIT_SUBMODULE_STRATEGY: normal
GIT_STRATEGY: fetch
GIT_DEPTH: 1

cache:
key: ${CI_JOB_NAME}

stages:
- build

Expand All @@ -10,18 +18,18 @@ Build:
# Add MSBuild.exe to path
- set PATH=%PATH%;C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin
# Update the CIBuildVersion.cs
- cd BACnetServerExample\BACnetServerExample
- "echo namespace BACnetServerExample{static class CIBuildVersion { public const int CIBUILDNUMBER = %CI_PIPELINE_IID%;}} > CIBuildVersion.cs"
- cd BACnetServerExample
- "echo namespace CASBACnetStack{static class CIBuildVersion { public const int CIBUILDNUMBER = %CI_PIPELINE_IID%;}} > CIBuildVersion.cs"
- type CIBuildVersion.cs
- cd ..\..\
- cd ..
script:
# Create the bin directory if it does not exist
- cd BACnetServerExample\BACnetServerExample
- cd BACnetServerExample
# Restore any nuget or other dependencies needed for the project
- msbuild /t:Restore /p:Configuration=Release /p:Platform=AnyCPU
- msbuild /t:Restore /p:Configuration=Release /p:Platform="Any CPU"
# Build and package the project in an apk for android
- msbuild /p:Configuration=Release /p:Platform=AnyCPU
- cd bin\..\
- msbuild /p:Configuration=Release /p:Platform="Any CPU"
- cd ..\bin
- dir
artifacts:
paths:
Expand Down
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[submodule "submodules/cas-bacnet-stack"]
path = submodules/cas-bacnet-stack
url = https://gitlab.com/chipkin/cas-bacnet-stack.git
url = ../../chipkin/cas-bacnet-stack.git
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
Expand All @@ -7,12 +7,16 @@

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<OutputPath>../../bin</OutputPath>
<OutputPath>../bin</OutputPath>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<OutputPath>../../bin</OutputPath>
<OutputPath>../bin</OutputPath>
</PropertyGroup>

<ItemGroup>
<Compile Include="..\submodules\cas-bacnet-stack\adapters\csharp\CASBACnetStackAdapter.cs" Link="CASBACnetStackAdapter.cs" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion BACnetServerExample/BACnetServerExample.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.28803.156
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BACnetServerExample", "BACnetServerExample\BACnetServerExample.csproj", "{F4321B8E-C000-4712-BC0A-D9F45DB15833}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BACnetServerExample", "BACnetServerExample.csproj", "{F4321B8E-C000-4712-BC0A-D9F45DB15833}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down
1,400 changes: 0 additions & 1,400 deletions BACnetServerExample/BACnetServerExample/CASBACnetStackAdapter.cs

This file was deleted.

2 changes: 0 additions & 2 deletions BACnetServerExample/BACnetServerExample/CIBuildVersion.cs

This file was deleted.

960 changes: 0 additions & 960 deletions BACnetServerExample/BACnetServerExample/Program.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using BACnetStackDLLServerCSharpExample;
using BACnetServerExample;
using CASBACnetStack;
using System;
using System.Collections.Generic;
using System.Text;
Expand Down
2 changes: 2 additions & 0 deletions BACnetServerExample/CIBuildVersion.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// This file is overwritten during the CI Build phase.
namespace CASBACnetStack { static class CIBuildVersion { public const int CIBUILDNUMBER = 0; } }
242 changes: 242 additions & 0 deletions BACnetServerExample/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
/**
* Windows BACnet Server Example Proprietary Property Sharp
* ----------------------------------------------------------------------------
* A BACnet server example that shows how to add proprietary property to an object
*
* More information https://github.com/chipkin/BACnetServerExampleProprietaryPropertyCSharp
*
* Created by: Steven Smethurst
* Created on: June 24, 2019
* Last updated: June 24, 2019
*/


using CASBACnetStack;
using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;

namespace BACnetServerExample
{
class Program
{
static void Main(string[] args)
{
BACnetServer bacnetServer = new BACnetServer();
bacnetServer.Run();
}

unsafe class BACnetServer
{
// UDP
UdpClient udpServer;
IPEndPoint RemoteIpEndPoint;

// Settings
const UInt16 SETTING_BACNET_PORT = 47808;

// A Database to hold the current state of the
private ExampleDatabase database = new ExampleDatabase();

// Version
const string APPLICATION_VERSION = "0.0.1";

public void Run()
{
Console.WriteLine("Starting Windows-BACnetServerExampleProprietaryPropertyCSharp version{0}.{1}", APPLICATION_VERSION, CIBuildVersion.CIBUILDNUMBER);
Console.WriteLine("https://github.com/chipkin/BACnetServerExampleProprietaryPropertyCSharp");
Console.WriteLine("FYI: BACnet Stack version: {0}.{1}.{2}.{3}",
CASBACnetStackAdapter.GetAPIMajorVersion(),
CASBACnetStackAdapter.GetAPIMinorVersion(),
CASBACnetStackAdapter.GetAPIPatchVersion(),
CASBACnetStackAdapter.GetAPIBuildVersion());

// Send/Recv callbacks.
CASBACnetStackAdapter.RegisterCallbackSendMessage(SendMessage);
CASBACnetStackAdapter.RegisterCallbackReceiveMessage(RecvMessage);
CASBACnetStackAdapter.RegisterCallbackGetSystemTime(CallbackGetSystemTime);

// Get Datatype Callbacks
CASBACnetStackAdapter.RegisterCallbackGetPropertyCharacterString(CallbackGetPropertyCharString);

// Set Datatype Callbacks
CASBACnetStackAdapter.RegisterCallbackSetPropertyCharacterString(CallbackSetPropertyCharacterString);


this.database.Setup();

// Add the device.
CASBACnetStackAdapter.AddDevice(this.database.Device.instance);

// Enable optional services
CASBACnetStackAdapter.SetServiceEnabled(database.Device.instance, CASBACnetStackAdapter.SERVICE_READ_PROPERTY_MULTIPLE, true);
CASBACnetStackAdapter.SetServiceEnabled(database.Device.instance, CASBACnetStackAdapter.SERVICE_WRITE_PROPERTY, true);
CASBACnetStackAdapter.SetServiceEnabled(database.Device.instance, CASBACnetStackAdapter.SERVICE_WRITE_PROPERTY_MULTIPLE, true);

// All done with the BACnet setup.
Console.WriteLine("FYI: CAS BACnet Stack Setup, successfuly");

// Open the BACnet port to recive messages.
this.udpServer = new UdpClient(SETTING_BACNET_PORT);
this.RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);

// Main loop.
Console.WriteLine("FYI: Starting main loop");
for (; ; )
{
CASBACnetStackAdapter.Loop();
database.Loop(); // Just for this example
}
}

private void DoUserInput()
{
if (Console.KeyAvailable)
{
ConsoleKeyInfo key = Console.ReadKey(true);
switch (key.Key)
{
case ConsoleKey.F1:
Console.WriteLine("FYI: BACnet Stack version: {0}.{1}.{2}.{3}",
CASBACnetStackAdapter.GetAPIMajorVersion(),
CASBACnetStackAdapter.GetAPIMinorVersion(),
CASBACnetStackAdapter.GetAPIPatchVersion(),
CASBACnetStackAdapter.GetAPIBuildVersion());
break;
default:
break;
}
}
}


public ulong CallbackGetSystemTime()
{
// https://stackoverflow.com/questions/9453101/how-do-i-get-epoch-time-in-c
return (ulong)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
}
public UInt16 SendMessage(System.Byte* message, UInt16 messageLength, System.Byte* connectionString, System.Byte connectionStringLength, System.Byte networkType, Boolean broadcast)
{
if (connectionStringLength < 6 || messageLength <= 0)
{
return 0;
}
// Extract the connection string into a IP address and port.
IPAddress ipAddress = new IPAddress(new byte[] { connectionString[0], connectionString[1], connectionString[2], connectionString[3] });
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, (connectionString[4] + connectionString[5] * 256));

// Debug
Console.WriteLine("FYI: Sending {0} bytes to {1}", messageLength, ipEndPoint.ToString());

// Copy from the unsafe pointer to a Byte array.
byte[] sendBytes = new byte[messageLength];
Marshal.Copy((IntPtr)message, sendBytes, 0, messageLength);

try
{
this.udpServer.Send(sendBytes, sendBytes.Length, ipEndPoint);
return (UInt16)sendBytes.Length;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}

return 0;
}
public UInt16 RecvMessage(System.Byte* message, UInt16 maxMessageLength, System.Byte* receivedConnectionString, System.Byte maxConnectionStringLength, System.Byte* receivedConnectionStringLength, System.Byte* networkType)
{
try
{
if (this.udpServer.Available > 0)
{
// Data buffer for incoming data.
byte[] receiveBytes = this.udpServer.Receive(ref this.RemoteIpEndPoint);
byte[] ipAddress = RemoteIpEndPoint.Address.GetAddressBytes();
byte[] port = BitConverter.GetBytes(UInt16.Parse(RemoteIpEndPoint.Port.ToString()));

// Copy from the unsafe pointer to a Byte array.
Marshal.Copy(receiveBytes, 0, (IntPtr)message, receiveBytes.Length);

// Copy the Connection string
Marshal.Copy(ipAddress, 0, (IntPtr)receivedConnectionString, 4);
Marshal.Copy(port, 0, (IntPtr)receivedConnectionString + 4, 2);
*receivedConnectionStringLength = 6;

// Debug
Console.WriteLine("FYI: Recving {0} bytes from {1}", receiveBytes.Length, RemoteIpEndPoint.ToString());

// Return length.
return (ushort)receiveBytes.Length;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
return 0;
}

private UInt32 UpdateStringAndReturnSize(System.Char* value, UInt32 maxElementCount, string stringAsVallue)
{
byte[] nameAsBuffer = ASCIIEncoding.ASCII.GetBytes(stringAsVallue);
UInt32 valueElementCount = maxElementCount;
if (nameAsBuffer.Length < valueElementCount)
{
valueElementCount = Convert.ToUInt32(nameAsBuffer.Length);
}
Marshal.Copy(nameAsBuffer, 0, (IntPtr)value, Convert.ToInt32(valueElementCount));
return valueElementCount;
}

public bool CallbackGetPropertyCharString(UInt32 deviceInstance, UInt16 objectType, UInt32 objectInstance, UInt32 propertyIdentifier, System.Char* value, UInt32* valueElementCount, UInt32 maxElementCount, System.Byte encodingType, bool useArrayIndex, UInt32 propertyArrayIndex)
{
Console.WriteLine("FYI: Request for CallbackGetPropertyCharString. objectType={0}, objectInstance={1}, propertyIdentifier={2}, propertyArrayIndex={3}", objectType, objectInstance, propertyIdentifier, propertyArrayIndex);

switch (objectType)
{
case CASBACnetStackAdapter.OBJECT_TYPE_DEVICE:
if (deviceInstance == database.Device.instance && objectInstance == database.Device.instance)
{
if (propertyIdentifier == CASBACnetStackAdapter.PROPERTY_IDENTIFIER_OBJECT_NAME)
{
*valueElementCount = UpdateStringAndReturnSize(value, maxElementCount, database.Device.name);
return true;
}
else if (propertyIdentifier == CASBACnetStackAdapter.PROPERTY_IDENTIFIER_MODEL_NAME)
{
*valueElementCount = UpdateStringAndReturnSize(value, maxElementCount, database.Device.modelName);
return true;
}
else if (propertyIdentifier == CASBACnetStackAdapter.PROPERTY_IDENTIFIER_VENDOR_NAME)
{
*valueElementCount = UpdateStringAndReturnSize(value, maxElementCount, database.Device.vendorName);
return true;
}
else if (propertyIdentifier == CASBACnetStackAdapter.PROPERTY_IDENTIFIER_APPLICATIONSOFTWAREVERSION)
{
string version = APPLICATION_VERSION + "." + CIBuildVersion.CIBUILDNUMBER;
*valueElementCount = UpdateStringAndReturnSize(value, maxElementCount, version);
return true;
}
}
break;
default:
break;
}

Console.WriteLine(" FYI: Not implmented. propertyIdentifier={0}", propertyIdentifier);
return false; // Could not handle this request.
}

bool CallbackSetPropertyCharacterString(UInt32 deviceInstance, UInt16 objectType, UInt32 objectInstance, UInt32 propertyIdentifier, char* value, UInt32 length, Byte encodingType, [In, MarshalAs(UnmanagedType.I1)] bool useArrayIndex, UInt32 propertyArrayIndex, System.Byte priority, UInt32* errorCode)
{
Console.WriteLine("FYI: Request for CallbackSetPropertyCharacterString. objectType={0}, objectInstance={1}, propertyIdentifier={2}, propertyArrayIndex={3}", objectType, objectInstance, propertyIdentifier, propertyArrayIndex);
Console.WriteLine(" FYI: Not implmented. propertyIdentifier={0}", propertyIdentifier);
return false;
}
}
}
}
2 changes: 1 addition & 1 deletion submodules/cas-bacnet-stack