Simple Server - Client problem?

Jun 15, 2011 at 11:57 AM

Hello!

Here's source for simple Server and Client running in a same win7 PC. Both programs compile nicely, but the client cannot

find the PV. Neither can caget, ca_info, etc. Both the server and the client have a same configuration file (included in the end).

Any ideas what is going wrong here?

SERVER:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using Epics;

namespace EpicsServerTest
{
    public partial class EpicsServerMain : Form
    {
        private EpicsServer Server;
        private EpicsRecord<double> record;

        public EpicsServerMain()
        {
            InitializeComponent();
            //Create the Server
            Server = new EpicsServer();
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            //create a new Record which serves a double
            record = Server.GetEpicsRecord<double>("OMA:Counter");

            lbLog.Items.Add("Record Created");

            //set HIGH-Alarm
            record.HIGH = 50;
            //set HIGH-Alert
            record.HIHI = 75;

            timer.Enabled = true;
            lbLog.Items.Add("Timer started");
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            //cpuTeller.Abort();

            timer.Enabled = false;
            lbLog.Items.Add("Timer stopped");
            record.VAL = 0;
            tbRecord.Text = record.VAL.ToString();
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            record.VAL = record.VAL + 1;
            tbRecord.Text = record.VAL.ToString();
        }
    }
}

 

CLIENT:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Epics;

namespace simpleEpicsLibraryExample
{
    public partial class Form1 : Form
    {
        EpicsClient client;
        EpicsChannel<string> monitoredChannel;
        EpicsChannel<double> channel;

        public Form1()
        {
            InitializeComponent();
            //Initialize the Client
            client = new EpicsClient();
            ConnectionTimer.Enabled = true;
        }

        private void btnPut_Click(object sender, EventArgs e)
        {
            string val = txtPutField.Text;

            //Put the value and wait till it is finished
            channel.PutSync(val);
        }

        private void btnGet_Click(object sender, EventArgs e)
        {
            double value = channel.Get<double>();
            lblGetValue.Text = value.ToString();
        }

        private void btnMonitor_Click(object sender, EventArgs e)
        {
            CreateMonitorChannel();
        }

        void monitoredChannel_MonitorChanged(EpicsChannel<string> sender, string newValue)
        {
            //switch the Thread-Context to write to the form
            this.BeginInvoke((MethodInvoker)delegate()
                {
                    //write the value to the label
                    lblMonitor.Text = newValue;
                }
            );
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            client.Dispose();
        }

        private void btnOpenChannel_Click(object sender, EventArgs e)
        {
            CreateChannel();
        }

        private void CreateChannel()
        {
            string ChannelName = txtChannel.Text;
            if (channel == null)
            {
                channel = client.CreateChannel<double>(ChannelName);
            }
            else
            {
                channel.Dispose();
                channel = client.CreateChannel<double>(ChannelName);
            }
        }

        private void btnOpenMonitorChannel_Click(object sender, EventArgs e)
        {
            CreateMonitorChannel();
        }

        private void CreateMonitorChannel()
        {
            string ChannelName = txtChannel.Text;
            if (monitoredChannel == null)
            {
                monitoredChannel = client.CreateChannel<string>(ChannelName);
                monitoredChannel.MonitorChanged += new EpicsDelegate<string>(monitoredChannel_MonitorChanged);
            }
            else
            {
                monitoredChannel.Dispose();
                monitoredChannel = client.CreateChannel<string>(ChannelName);
                monitoredChannel.MonitorChanged += new EpicsDelegate<string>(monitoredChannel_MonitorChanged);
            }
        }

        private void btnDisposeChannel_Click(object sender, EventArgs e)
        {
            if (channel != null)
            {
                channel.Dispose();
                tbChannelStatus.Text = "Not Connected";
            }
        }

        private void btnCloseMonitorChannel_Click(object sender, EventArgs e)
        {
            //check if a channel is already monitored, if so close it
            if (monitoredChannel != null)
            {
                monitoredChannel.Dispose();
                tbMonitorChannelStatus.Text = "Not Connected";
            }
        }

        private void ConnectionTimer_Tick(object sender, EventArgs e)
        {
            if (channel != null)
            {
                tbChannelStatus.Text = channel.Status.ToString();
            }
            else
            {
                tbChannelStatus.Text = "Not Connected";
            }

            if (monitoredChannel != null)
            {
                tbMonitorChannelStatus.Text = monitoredChannel.Status.ToString();
            }
            else
            {
                tbMonitorChannelStatus.Text = "Not Connected";
            }
        }

        private void btnClientStatus_Click(object sender, EventArgs e)
        {
            MessageBox.Show(client.GetStatus());
        }
    }
}

 

AND THE EPICS.NET.Library.dll.config:

<?xml version="1.0"?>

<configuration>
  <configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
      <section name="EPICS.Properties.EpicsSettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <appSettings>
    <add key="e#GetTimeout" value="5000" />
    <add key="e#ServerList" value="127.0.0.1:5064" />
    <add key="e#ConnectTimeout" value="5000" />
    <add key="e#channelSearchInterval" value="100" />
    <add key="e#channelSearchMaxPackageSize" value="300" />
    <add key="e#TCPMaxSendSize" value="4096" />
    <add key="ClientSettingsProvider.ServiceUri" value="" />
  </appSettings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
  </startup>
  <system.web>
    <membership defaultProvider="ClientAuthenticationMembershipProvider">
      <providers>
        <add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
      </providers>
    </membership>
    <roleManager defaultProvider="ClientRoleProvider" enabled="true">
      <providers>
        <add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
      </providers>
    </roleManager>
  </system.web>
</configuration>

 

 

BR,

Matti

Coordinator
Jun 15, 2011 at 1:04 PM
Edited Jun 15, 2011 at 1:05 PM

As I don't have the full source code to our app, I couldn't properly replicate the problem. Here is what I've done on a sample console app:

 

static void Main(string[] args)
{
	// A new thread is not necessary, a separate thread is already created by the server.
	// This is just for diagnostics purposes. Simply calling 'CreateServer();' would also be fine.
	Task.Factory.StartNew(() => CreateServer());

	var client = new EpicsClient();
	var monitor = client.CreateChannel("OMA:Counter");
	Console.WriteLine(monitor.Get());
	Console.ReadKey();
}

private static void CreateServer()
{
	var server = new EpicsServer();
	var record = server.GetEpicsRecord<double>("OMA:Counter");
	record.HIGH = 50;
	record.HIHI = 75;
	record.VAL = 19;
}

 

This basicaly writes "19" to the console and waits for the user to press a button. While waiting for the user to press a button, it is also responsive to all caget, ca_info, etc. requests. If you post relevant project as a zip file, I can inspect further. Other than that, you can get this as a starting point.

Jun 16, 2011 at 7:58 AM

using Epics;

namespace Epics_NET_console_test
{
    class Program
    {
        static void Main(string[] args)
        {
            // A new thread is not necessary, a separate thread is already created by the server.
            // This is just for diagnostics purposes. Simply calling 'CreateServer();' would also be fine.
            //Task.Factory.StartNew(() => CreateServer());
            CreateServer();

            var client = new EpicsClient();
            var monitor = client.CreateChannel("OMA:Counter");
            Console.WriteLine(monitor.Get());
            Console.ReadKey();
        }

        private static void CreateServer()
        {
            var server = new EpicsServer();
            var record = server.GetEpicsRecord<double>("OMA:Counter");
            record.HIGH = 50;
            record.HIHI = 75;
            record.VAL = 19;
        }
    }
}

 

This doesn't work. With or without configuration file. Configuration file is "original", but the IP is 127.0.0.1:5064

Jun 16, 2011 at 10:00 AM

Now that I found the System.Threading.Tasks.Task -class, I tried the exactly same code that you presented in the message #2.

Same story. The console just blinks the cursor... And the when I debugged the code, the monitor.status stays REQUESTED.

Is this a configuration issue? Or is this Windows7 issue? Firewall is disabled.

 

Matti

Jun 16, 2011 at 10:41 AM

Yes!!

I got it. It is configuration issue. When I added following lines after the client and server instantiation, everything started working:

 

            var client = new EpicsClient();
            client.Config.ServerList.Add("127.0.0.1:5064");

 

            var server = new EpicsServer();
            server.Config.ListenIP = "127.0.0.1";
            server.Config.TCPPort = 5064;
            server.Config.UDPPort = 5064;

 

Now the question is: where the "EPICS.NET.Library.dll.config" -file should be?

I have it in the ../bin/debug/ next to the "EPICS.NET.Library.dll"

It seems that it is not read by the server constructor or client constructor?

 

Matti

Coordinator
Jun 16, 2011 at 9:33 PM
Edited Jun 16, 2011 at 9:36 PM

From within your application, all your configuration is red from your app.config file thus "EPICS.NET.Library.dll.config" is simply ignored. This is the usual case for any library actually. System.Config is designed to work that way. This is because the host application is responsible to feed all the client libraries with the required configuration. What you can do is to merge "EPICS.NET.Library.dll.config" into your host application's app.config file (or simply copy the contents of it to your app.config file if it is empty). Or, you can store all your configuration in your application configuration section and read them like:

client.Config.ServerList.Add(Properties.Settings.Default.ServerIP);
which is generally regarded as a good practice since it makes unit/integration testing easier.