Skip to content

Commit

Permalink
Updated README and added J1939 Example Code - Closes #42
Browse files Browse the repository at this point in the history
  • Loading branch information
derek-will committed Sep 18, 2022
1 parent 8d49853 commit 3772534
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 1 deletion.
59 changes: 58 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,71 @@ using (SafeFileDescriptorHandle testerSocketHandle = LibcNativeMethods.Socket(So
}
```

### SAE J1939 Support

#### Object-Oriented Style
```cs
var vcan0 = CanNetworkInterface.GetAllInterfaces(true).FirstOrDefault(iface => iface.Name.Equals("vcan0"));

using (var j1939Socket = new J1939CanSocket())
{
j1939Socket.EnableBroadcast = true;
j1939Socket.SendPriority = 3;
j1939Socket.Bind(vcan0, SocketCanConstants.J1939_NO_NAME, 0x0F004, 0x01);
var destAddr = new SockAddrCanJ1939(vcan0.Index)
{
Name = SocketCanConstants.J1939_NO_NAME,
PGN = 0x0F004,
Address = SocketCanConstants.J1939_NO_ADDR,
};
j1939Socket.WriteTo(new byte[] { 0xFF, 0xFF, 0xFF, 0x6C, 0x50, 0xFF, 0xFF, 0xFF }, MessageFlags.None, destAddr);
}
```

#### Procedural Style
```cs
using (var j1939Handle = LibcNativeMethods.Socket(SocketCanConstants.PF_CAN, SocketType.Dgram, SocketCanProtocolType.CAN_J1939))
{
var ifr = new Ifreq("vcan0");
int ioctlResult = LibcNativeMethods.Ioctl(j1939Handle, SocketCanConstants.SIOCGIFINDEX, ifr);

int value = 1;
int enableBroadcastResult = LibcNativeMethods.SetSockOpt(j1939Handle, SocketLevel.SOL_SOCKET, SocketLevelOptions.SO_BROADCAST, ref value, Marshal.SizeOf(typeof(int)));

int prio = 3;
int prioResult = LibcNativeMethods.SetSockOpt(j1939Handle, SocketLevel.SOL_CAN_J1939, J1939SocketOptions.SO_J1939_SEND_PRIO, ref prio, Marshal.SizeOf(typeof(int)));

var srcAddr = new SockAddrCanJ1939(ifr.IfIndex)
{
Name = SocketCanConstants.J1939_NO_NAME,
PGN = 0x0F004,
Address = 0x01,
};
int bindResult = LibcNativeMethods.Bind(j1939Handle, srcAddr, Marshal.SizeOf(typeof(SockAddrCanJ1939)));;

var dstAddr = new SockAddrCanJ1939(vcan0.Index)
{
Name = SocketCanConstants.J1939_NO_NAME,
PGN = 0x0F004,
Address = SocketCanConstants.J1939_NO_ADDR,
};
byte[] data = new byte[] { 0xFF, 0xFF, 0xFF, 0x34, 0x12, 0xFF, 0xFF, 0xFF };
int sendToResult = LibcNativeMethods.SendTo(j1939Handle, data, data.Length, MessageFlags.None, dstAddr, Marshal.SizeOf(typeof(SockAddrCanJ1939)));
}
```

### Other SocketCAN features
J1939 and BCM (Broadcast Manager) are supported by this library, but currently only at the basic level of providing a procedural style interface. Object-Oriented support for these socket types are planned to be implemented and released in the future.
BCM (Broadcast Manager) is also supported by this library, but currently only at the basic level of providing a procedural style interface. Object-Oriented support for BCM is planned to be implemented and released in the future.

### Supported Environments
Thorough testing has been done for x64, ARM32 and ARM64 on Linux. Support for Raw CAN and BCM have been confirmed as far back as Linux Kernel 4.9. Testing on Alpine Linux has not been carried out yet.

### Example Code

* CanBusSniffer : Simple CAN bus analyzer
* IsoTpCommSimulator : ISO-TP communication simulation
* ObjectOrientedDiagAppSimulator : Diagnostic Application Simulator using IsoTpCanSocket objects
* J1939EngineSpeedTransmit : Simple application that sends the J1939 Engine Speed signal a couple of different ways using SocketCAN#


### Additional Information:
Expand Down
14 changes: 14 additions & 0 deletions SocketCANSharp.sln
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IsoTpCommSimulator", "examp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ObjectOrientedDiagAppSimulator", "examples\ObjectOrientedDiagAppSimulator\ObjectOrientedDiagAppSimulator.csproj", "{B3212B61-1B39-4EB1-8BD0-C54049F44BBC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "J1939EngineSpeedTransmit", "examples\J1939EngineSpeedTransmit\J1939EngineSpeedTransmit.csproj", "{F55AD00A-13BB-4CD8-B17F-105192105518}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -86,5 +88,17 @@ Global
{B3212B61-1B39-4EB1-8BD0-C54049F44BBC}.Release|x64.Build.0 = Release|Any CPU
{B3212B61-1B39-4EB1-8BD0-C54049F44BBC}.Release|x86.ActiveCfg = Release|Any CPU
{B3212B61-1B39-4EB1-8BD0-C54049F44BBC}.Release|x86.Build.0 = Release|Any CPU
{F55AD00A-13BB-4CD8-B17F-105192105518}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F55AD00A-13BB-4CD8-B17F-105192105518}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F55AD00A-13BB-4CD8-B17F-105192105518}.Debug|x64.ActiveCfg = Debug|Any CPU
{F55AD00A-13BB-4CD8-B17F-105192105518}.Debug|x64.Build.0 = Debug|Any CPU
{F55AD00A-13BB-4CD8-B17F-105192105518}.Debug|x86.ActiveCfg = Debug|Any CPU
{F55AD00A-13BB-4CD8-B17F-105192105518}.Debug|x86.Build.0 = Debug|Any CPU
{F55AD00A-13BB-4CD8-B17F-105192105518}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F55AD00A-13BB-4CD8-B17F-105192105518}.Release|Any CPU.Build.0 = Release|Any CPU
{F55AD00A-13BB-4CD8-B17F-105192105518}.Release|x64.ActiveCfg = Release|Any CPU
{F55AD00A-13BB-4CD8-B17F-105192105518}.Release|x64.Build.0 = Release|Any CPU
{F55AD00A-13BB-4CD8-B17F-105192105518}.Release|x86.ActiveCfg = Release|Any CPU
{F55AD00A-13BB-4CD8-B17F-105192105518}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
14 changes: 14 additions & 0 deletions examples/J1939EngineSpeedTransmit/J1939EngineSpeedTransmit.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\SocketCANSharp\SocketCANSharp.csproj" />
</ItemGroup>

</Project>
104 changes: 104 additions & 0 deletions examples/J1939EngineSpeedTransmit/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#region License
/*
BSD 3-Clause License
Copyright (c) 2022, Derek Will
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#endregion

using System.Net.Sockets;
using System.Runtime.InteropServices;
using SocketCANSharp;
using SocketCANSharp.Network;

namespace J1939EngineSpeedTransmit
{
/// <summary>
/// Really basic J1939 program to show how to use SocketCAN# for J1939.
/// </summary>
class Program
{
static void Main(string[] args)
{
var vcan0 = CanNetworkInterface.GetAllInterfaces(true).FirstOrDefault(iface => iface.Name.Equals("vcan0"));
if (vcan0 == null)
{
Console.WriteLine("vcan0 interface not found!");
return;
}

using (var j1939Socket = new J1939CanSocket())
{
j1939Socket.EnableBroadcast = true;
j1939Socket.SendPriority = 3;
j1939Socket.Bind(vcan0, SocketCanConstants.J1939_NO_NAME, 0x0F004, 0x01);
var destAddr = new SockAddrCanJ1939(vcan0.Index)
{
Name = SocketCanConstants.J1939_NO_NAME,
PGN = 0x0F004,
Address = SocketCanConstants.J1939_NO_ADDR,
};
// Engine Speed: 2573.5 RPM (0x506C -> 20588 * 0.125)
j1939Socket.WriteTo(new byte[] { 0xFF, 0xFF, 0xFF, 0x6C, 0x50, 0xFF, 0xFF, 0xFF }, MessageFlags.None, destAddr);
// candump: vcan0 0CF00401 [8] FF FF FF 6C 50 FF FF FF
}

using (var j1939Handle = LibcNativeMethods.Socket(SocketCanConstants.PF_CAN, SocketType.Dgram, SocketCanProtocolType.CAN_J1939))
{
var ifr = new Ifreq("vcan0");
int ioctlResult = LibcNativeMethods.Ioctl(j1939Handle, SocketCanConstants.SIOCGIFINDEX, ifr);

int value = 1;
int enableBroadcastResult = LibcNativeMethods.SetSockOpt(j1939Handle, SocketLevel.SOL_SOCKET, SocketLevelOptions.SO_BROADCAST, ref value, Marshal.SizeOf(typeof(int)));

int prio = 3;
int prioResult = LibcNativeMethods.SetSockOpt(j1939Handle, SocketLevel.SOL_CAN_J1939, J1939SocketOptions.SO_J1939_SEND_PRIO, ref prio, Marshal.SizeOf(typeof(int)));

var srcAddr = new SockAddrCanJ1939(ifr.IfIndex)
{
Name = SocketCanConstants.J1939_NO_NAME,
PGN = 0x0F004,
Address = 0x01,
};
int bindResult = LibcNativeMethods.Bind(j1939Handle, srcAddr, Marshal.SizeOf(typeof(SockAddrCanJ1939)));;

var dstAddr = new SockAddrCanJ1939(vcan0.Index)
{
Name = SocketCanConstants.J1939_NO_NAME,
PGN = 0x0F004,
Address = SocketCanConstants.J1939_NO_ADDR,
};
// Engine Speed: 582.5 RPM (0x1234 -> 4660 * 0.125)
byte[] data = new byte[] { 0xFF, 0xFF, 0xFF, 0x34, 0x12, 0xFF, 0xFF, 0xFF };
int sendToResult = LibcNativeMethods.SendTo(j1939Handle, data, data.Length, MessageFlags.None, dstAddr, Marshal.SizeOf(typeof(SockAddrCanJ1939)));
// candump: vcan0 0CF00401 [8] FF FF FF 34 12 FF FF FF
}
}
}
}

0 comments on commit 3772534

Please sign in to comment.