Create the event class
This class must give four properties to store information provided by the machine coffee machine. All event inside LeCouteauSuisse must derive from the class GeneratorEvent wich give the minimum set of properties and initialize the class.
- Add a new class named 'MachineAlertEvent'
- Add the namespace LeCouteauSuisse.API with the using directive
- Change class to public
- This class must derived from 'GeneratorEvent'
- Add four private string fields named kind, localisation, product, quantity
- Add four public properties with the get accessor only to read each field
- Add a new constructor with 7 arguments, in this order :
- string serviceName : the name of the service
- string generatorName : the name of the generator
- EventPriority defaultPriority : the default priority configured for this generator
- string kind : the kind of the coffee machine, this information is provided by the coffee machine
- string localisation : the localisation of the coffee machine, this information is provided by the coffee machine
- string product : the product name missing for the coffee machine, this information is provided by the coffee machine
- string quantity : the quantity of the product, this information is provided by the coffee machine
- Call the base constructor with the three first arguments
- Initialize the four fields kind, localisation, product and quantity with each parameter
This class will looks like :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LeCouteauSuisse.API;
namespace CoffeeSupplyChainLibrary
{
public class MachineAlertEvent : GeneratorEvent
{
string kind, localisation, product, quantity;
public MachineAlertEvent(string serviceName, string generatorName, EventPriority defaultPriority, string kind, string localisation, string product, string quantity)
: base(serviceName, generatorName, defaultPriority)
{
this.kind = kind;
this.localisation = localisation;
this.product = product;
this.quantity = quantity;
}
public string Quantity
{
get { return quantity; }
}
public string Product
{
get { return product; }
}
public string Localisation
{
get { return localisation; }
}
public string Kind
{
get { return kind; }
}
}
}
Create the generator
The generator will serve has a TCP server to wait an alert of a coffee machine. When an alert is send, a connection on a specific TCP port is establish and information is send on this TCP connection.
- Add a new class named 'MachineAlertGenerator'
- Add namespace LeCouteauSuisse.API, System.Net and System.Net.Sockets with the using directive
- Change class to public
- This class must derived from 'BaseGenerator'
- Add a private int field named alertTcpPort.
- Override the method Initialize. In this method we will read configuration from the .config file in the <settings> section of the generator. We want to add the TCP port number with a parameter named 'alertTcpPort'. To read configuration we used 'context.Initialization.GetAttribute' method.
- Override the method Run. In this method we will wait for a TCP connection and read information to send an event using the MachineAlertEvent class. Event are created with context.GetNewGeneratorEvent method and send with base.OnNewEvent method. This method will :
- Create a loop checking if service is stopping
- Create a TCP listener
- Check for pending connection requests
- Open a connection, read informations, send an event of type MachineAlertEvent
This class will looks like :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LeCouteauSuisse.API;
using System.Net;
using System.Net.Sockets;
namespace CoffeeSupplyChainLibrary
{
public class MachineAlertGenerator : BaseGenerator
{
const int DEFAULT_TCP_PORT = 12121;
int alertTcpPort;
public override void Initialize(GeneratorContext ctx)
{
// call the base class BaseGenerator to initialize generator
base.Initialize(ctx);
// read alertTcpPort attribute from configuration file using context.Initialization.GetAttribute method
// if none attribute is found assign a default TCP port number (12121)
if (!int.TryParse(context.Initialization.GetAttribute("alertTcpPort"), out alertTcpPort))
alertTcpPort = DEFAULT_TCP_PORT;
// send information to logger
context.Logger.Write(LoggerLevel.Information, "MachineAlertGenerator " + context.Name + " initialized");
}
public override void Run()
{
TcpListener listener;
// send information to logger, the generator is running
context.Logger.Write(LoggerLevel.Information, "MachineAlertGenerator " + context.Name + " started");
try
{
// create the listener and wait on alertTcpPort port
listener = new TcpListener(IPAddress.Any, alertTcpPort);
// start the listener
listener.Start();
while (!MustStop) // check if service must stop, if service is stopping the loop will break
{
// check if a new connection is available
while (listener.Pending())
{
byte[] buffer = new byte[256];
int lengthMessage;
string message, kind, localisation, product, quantity;
MachineAlertEvent eventArgs;
TcpClient client = listener.AcceptTcpClient();
NetworkStream stream = client.GetStream();
// a message alert is 256 bytes length
// structure of message alert is :
// [0,63] : kind
// [64,127] : localisation
// [128,191] : product
// [192,255] : quantity
lengthMessage = 0;
while (lengthMessage < 256)
{
if (stream.DataAvailable)
lengthMessage += stream.Read(buffer, lengthMessage, buffer.Length);
else if (WaitStop(100)) // check if must stop or wait for data
break;
}
stream.Close();
stream.Dispose();
client.Close();
// we have a completed message, convert to string and split message
ASCIIEncoding encoding = new ASCIIEncoding();
message = encoding.GetString(buffer);
kind = message.Substring(0, 64);
localisation = message.Substring(64, 64);
product = message.Substring(128, 64);
quantity = message.Substring(192, 64);
// create an event alert and send it
context.Logger.Write(LoggerLevel.Information, "MachineAlertGenerator " + context.Name + " launch an event");
// give specific information for MachineAlertEvent
Object[] args = new Object[4];
args[0] = kind;
args[1] = localisation;
args[2] = product;
args[3] = quantity;
// create event
eventArgs = (MachineAlertEvent)context.GetNewGeneratorEvent(typeof(MachineAlertEvent), args);
// send event
base.OnNewEvent(eventArgs);
}
// sleep 100 ms
if (WaitStop(100))
break;
}
listener.Stop();
}
catch (Exception ex) { context.Logger.Write(LoggerLevel.Error, "MachineAlertGenerator " + context.Name + " error", ex); }
// send information to logger, the generator is stopping
context.Logger.Write(LoggerLevel.Information, "MachineAlertGenerator " + context.Name + " stopped");
}
}
}