OmniSharp – Making cross-platform .NET a reality, and a pleasure

In case you missed it, make sure to read Announcing .NET 2015 – .NET as Open Source, .NET on Mac and Linux, and Visual Studio Community because there’s been some big stuff going on.

Here’s the summary of the .NET 2015 Wave of awesomeness.

The other thing I wanted to talk about is a newly organized group of technologies called OmniSharp. Just to be sure there’s no confusion, OmniSharp isn’t a Microsoft project. While there are two Microsoft folks on the team of 8 or so, we are working on it as community members, not in an official capacity.

I “launched” this project in my talk at the Connect() mini-conference in New York a few weeks back. You can watch that video here on Channel 9 now if you like. However, the technologies around and under OmniSharp have been around for years…like over a decade!

As a team and a community we pulled together a bunch of projects and plugins, got organized, and created https://github.com/omnisharp and http://www.omnisharp.net. Jonathan Channon has a great overview blog post you should check out that talks about how Jason Imison created OmniSharpServerwhich is an…

HTTP wrapper around NRefactory allowing C# editor plugins to be written in any language. NRefactory is the C# analysis library used in the SharpDevelop and MonoDevelop IDEs. It allows applications to easily analyze both syntax and semantics of C# programs. It is quite similar to Microsoft’s Roslyn project; except that it is not a full compiler – NRefactory only analyzes C# code, it does not generate IL code.

OmniSharp runs as its own process and runs a local Nancy-based web api that your editor of choice talks to. If you have an editor that you like to use, why not get involved and make a plugin? Perhaps for Eclipse?

We now have plugins for these editors:

  • Sublime
  • Brackets from Adobe
  • Atom from GitHub
  • Emacs
  • Vim

And these work on (so far) all platforms! It’s about choice. We wanted to bring more than autocomplete (which is basically “I think you typed that before”) to your editor, instead we want actual type-smart intellisense, as well as more sophisticated features like refactoring, format document, and lots of other stuff you’d expect only to see in Visual Studio.

We also brought in the Sublime Kulture package which gives Sublime users support for ASP.NET 5 (formerly ASP.NET vNext), so they can launch Kestrel (our libuv based local webserver), run Entity Framework migrations, and other arbitrary commands from within Sublime.

.NET in Sublime, in Vim, in Brackets, in Atom, and everywhere else, cross-platform

Here’s OmniSharp running in emacs on my Windows machine. The emacs setup (here is an example) is a little more complex than the others, but it also gives emacs folks an extreme level of control. Note that I had to launch the OmniSharp server manually for emacs, while it launches automatically for the other editors.

image

Here is an ASP.NET MVC app running in Sublime. The Sublime OmniSharp package output can be seen in the debug console there (Ctrl+~ to see it).

image

OmniSharp is in very active development. We are looking at bringing in Roslyn, using the new ASP.NET Design Time Host, and improving robustness. It’s not perfect, but it’s pretty darn cool. There’s lots of details in Jonathan̵

7;s writeup with great animated gifs showing features. Also note that we have a Yeoman generator for ASP.NET that can get you started when creating ASP.NET 5 apps on Mac or Linux. The yeoman generator can create Console apps, MVC apps, and NancyFx apps.

You can get started at http://omnisharp.net.  See you there!

via: http://www.hanselman.com/blog/OmniSharpMakingCrossplatformNETARealityAndAPleasure.aspx

Modbus with C#: libraries, code, utilities and examples

In this post you will find how to use nModbus with C# and how to create a simulation enviroment to test your program with Modbus.
Other useful resources that you can find in this post are:

  • using a Modbus simulator
  • Creating virtual Com ports
  • Using sniffer tools to debug the transmission
  • A Modbus TCP Client in C# with another library

Getting NModbus

The C# library that i use the most when i need Modbus communication between pc and plcs or other components is nModbus.
nModbus manages both Modbus TCP and RTU protocols, it’s well tested and sources are available. The site for nModbus is http://code.google.com/p/nmodbus/and here you can get the latest sources.

Once you extract the sources you can open the solution file, located in the src folder.

Sample code

NModbus contains many samples included in the source code. Once you open it, you can watch at the MySample project that contains many examples on how to read and write using different devices:

The two examples that i use the most are Modbus TCP and RTU, and an example of the code to use the library is this:

Modbus TCP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
 *  Reading
 */
TcpClient client = new TcpClient("127.0.0.1", 502);
ModbusIpMaster master = ModbusIpMaster.CreateIp(client);
// read five input values
ushort startAddress = 100;
ushort numInputs = 5;
bool[] inputs = master.ReadInputs(startAddress, numInputs);
for (int i = 0; i < numInputs; i++)
    Console.WriteLine("Input {0}={1}", startAddress + i, inputs[i] ? 1 : 0);
/*
 *  Writing
 */
ushort startAddress = 1;
// write three coils
master.WriteMultipleCoils(startAddress, new bool[] { true, false, true });

Modbus RTU

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
SerialPort port = new SerialPort("COM1");
// configure serial port
port.BaudRate = 9600;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.Open();
// create modbus master
IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(port);
byte slaveId = 1;
ushort startAddress = 1;
ushort numRegisters = 5;
// read five registers
ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, numRegisters);
for (int i = 0; i < numRegisters; i++)
    Console.WriteLine("Register {0}={1}", startAddress + i, registers[i]);
byte slaveId = 1;
ushort startAddress = 1;
// write three coils
master.WriteMultipleCoils(slaveId, startAddress, new bool[] { true, false, true });

Depending on the registers that you are going to read and write you have different methods, that will call the different functions of the protocol, and that will return the results in 2 formats: ushort or bool (if you are reading multiple registers you will get array of ushorts and bools).

ITDONOTWORK

NModbus is supported by thousands of users, and you can find help on the NModbus google Group.

Testing your program with a simulation:

The most common Modbus simulator is located at http://www.plcsimulator.org/

This simulator provides both Modbus TCP and RTU protocols, and shows the content of the registers in the main windows so you can analyze the behaviour of your program directly in the tables of the simulator.

Creating Virtual COM Ports to test Modbus RTU:

While it’s easy to use TCP to analyze the Modbus TCP on the host (just create a socket with a 127.0.0.1 ip), testing Modbus RTU or ASCII may require some hardware, like a null-modem cable and 2 COM Ports.
To avoid this you can download a null modem emulator called Com0Com (open source, located at http://sourceforge.net/projects/com0com/) to create a pair of virtual com ports wich you can use to connect your simulator and software.

Sniffer tools available for free:

If you need to analyze the traffic between the 2 devices, to see what’s going on with your communication, there are 2 useful tools:
Wireshark is used to sniff ethernet packets and to decode the protocol. This tool can decode Modbus TCP protocol quite good and it’s useful to debug the transmission.
Free Serial Port Monitor is a serial port sniffer that can analyze the transmission between 2 COM Ports.

Other Modbus TCP libraries:

a good Modbus TCP library is available athttp://www.codeproject.com/Articles/16260/Modbus-TCP-class

This library offers a client with some interesting features and it’s also useful when debugging devices.

via: http://www.mesta-automation.com/modbus-with-c-sharp-libraries-examples/

Creating Log4Net appenders programatically in C#

In most cases using log4net’s xml configuration is best to set up how your application will log. However I found it more practical to create the configuration programatically in a shared c# file, to easily add common options between my applications. First create a static class to hold the following methods and add using:

using log4net;
using log4net.Core;
using log4net.Repository.Hierarchy;
using log4net.Appender;
using log4net.Layout;
using log4net.Filter;

A file appender

        public static IAppender CreateFileAppender(string appCode)
        {
            var appender = new RollingFileAppender
            {
                Name = "RollingFileAppender",
                File = String.Format(@"C:\logs\{0}.log", appCode),
                AppendToFile = false,
                RollingStyle = RollingFileAppender.RollingMode.Size,
                MaxSizeRollBackups = 10,
                MaximumFileSize = "100MB"
            };

            var layout = new PatternLayout
            {
                ConversionPattern = "%newline%date %-5level %logger – %message – %property%newline"
            };

            layout.ActivateOptions();

            appender.Layout = layout;
            appender.ActivateOptions();

            return appender;
        }

A console appender

        public static IAppender CreateConsoleAppender()
        {
            var appender = new ConsoleAppender {Name = "ConsoleAppender"};
            var layout = new PatternLayout
            {
                ConversionPattern = "%newline%date %-5level %logger – %message – %property%newline"
            };

            layout.ActivateOptions();
            appender.Layout = layout;
            appender.ActivateOptions();

            return appender;
        }

An ADO.NET appender

        public static IAppender CreateAdoNetAppender(string cs)
        {
            var appender = new AdoNetAppender
            {
                Name = "AdoNetAppender",
                BufferSize = 1,
                ConnectionType = "System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
                ConnectionString = cs,
                CommandText = @"INSERT INTO Log ([Date], [Thread], [Level], [Logger], [Message], [Exception], [User], [Ip]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception, @user, @ip)"
            };

            AddDateTimeParameterToAppender(appender, "log_date");
            AddStringParameterToAppender(appender, "thread", 255, "%thread");
            AddStringParameterToAppender(appender, "log_level", 50, "%level");
            AddStringParameterToAppender(appender, "logger", 255, "%logger");
            AddStringParameterToAppender(appender, "message", 4000, "%message");
            AddStringParameterToAppender(appender, "user", 50, "%aspnet-request{AUTH_USER}");
            AddStringParameterToAppender(appender, "ip", 15, "%aspnet-request{REMOTE_ADDR}");
            AddErrorParameterToAppender(appender, "exception", 2000);
            appender.ActivateOptions();
            
            return appender;
        }

The above requires 3 helper functions:

        public static void AddStringParameterToAppender(this AdoNetAppender appender, string paramName, int size, string conversionPattern)
        {
            var param = new AdoNetAppenderParameter
            {
                ParameterName = paramName,
                DbType = System.Data.DbType.String,
                Size = size,
                Layout = new Layout2RawLayoutAdapter(new PatternLayout(conversionPattern))
            };
            appender.AddParameter(param);
        }
        public static void AddDateTimeParameterToAppender(this AdoNetAppender appender, string paramName)
        {
            var param = new AdoNetAppenderParameter
            {
                ParameterName = paramName,
                DbType = System.Data.DbType.DateTime,
                Layout = new RawUtcTimeStampLayout()
            };
            appender.AddParameter(param);
        }
        public static void AddErrorParameterToAppender(this AdoNetAppender appender, string paramName, int size)
        {
            var param = new AdoNetAppenderParameter
            {
                ParameterName = paramName,
                DbType = System.Data.DbType.String,
                Size = size,
                Layout = new Layout2RawLayoutAdapter(new ExceptionLayout())
            };
            appender.AddParameter(param);
        }

Initializing log4net

Now you can easily initialize log4not in the startup of your application. Here are some extra helper functions:

        public static void ConfigureWithFile(string appCode)
        {
            var h = (Hierarchy)LogManager.GetRepository();
            h.Root.Level = Level.All;
            h.Root.AddAppender(CreateFileAppender(appCode));
            h.Configured = true;
        }
        public static void ConfigureWithDb(string cs, bool onlyErrors)
        {
            var h = (Hierarchy)LogManager.GetRepository();
            h.Root.Level = Level.All;

            var ado = CreateAdoNetAppender(cs);
            h.Root.AddAppender(ado);

            if (onlyErrors)
            {
                var filter = new LevelRangeFilter {LevelMin = Level.Error};
                ((AppenderSkeleton)ado).AddFilter(filter);
            }

            h.Configured = true;
        }

So now, if example you have a web application:

protected void Application_Start(object sender, EventArgs e)
{
LogHelpers.ConfigureWithDb(@"Data Source=.\SQL2008;Initial Catalog=Today;Integrated Security=True",false);
LogHelpers.ConfigureWithFile("MyWebApp");
}

The above would log to the database (only the errors) plus a file (all log levels). The rest is all the same, e.g. to get the logger instance:

public static readonly ILog Log = LogManager.GetLogger(typeof(MyClass));

via: http://codesofair.wordpress.com/2012/02/01/creating-log4net-appenders-programatically-in-c/