View on GitHub

Opcweb

Simple Web web api and signalr server hosting OPC client

Download this project as a .zip file Download this project as a tar.gz file

OpcWeb

Data from Opc-ua/Opc-da (or plug in your own source) servers exposed via Web api and signalr

REST interface to add modify and remove devices nodes and scan classes, set and read nodes

subscribe to nodes with SignalR, x-sockets (or plug in your own technology)

opc-da and opc-ua access use OPCLabs opc client s/w

API

OpcScan

PUT api/OpcScan send an array of node ids and get their current values

OpcWrite

PUT api/OpcWrite send an array of node ids and write their values

Node

PUT api/Node/{zone} Add/modify nodes to a zone

GET api/Node/{zone} Get nodes in a zone

DELETE api/Node/{zone}?ids[0]={ids[0]}&ids[1]={ids[1]} Delete a node from a zone

OpcWrite

PUT api/OpcWrite/{zone} write an array of nodes

Device

PUT api/Device/{zone} Add/modify a Device in a zone(Opc server&device)

GET api/Device/{zone} Get Devices is a zone

DELETE api/Device/{zone}?ids[0]={ids[0]}&ids[1]={ids[1]} Delete a Device from a zone

ScanClass

PUT api/ScanClass/{zone} Add/modify scanclasses to a zone

GET api/ScanClass/{zone} Get scan classes in a zone

DELETE api/ScanClass/{zone}?ids[0]={ids[0]}&ids[1]={ids[1]} Delete scan classes from a zone

Zone

PUT api/Zone Reset all zones

PUT api/Zone/{zone} Reset a zone

GET api/Zone Get zones

Knockout binding

Knockout binding to display the value of a node on the serve live (if you don't like it write your own)

{{#nodeValue:100}}
    {{$nodeValue().Value}}
{{/nodeValue}}

Enter node id and get data

view model is

{
    id:ko.observable()
}
<script data-main="/Scripts/App/SimpleApp" type="text/javascript" src="/Scripts/require.js"></script>
<h1>Simple</h1>
<div style="display:none" data-bind="attr:{style:'display:block'}">
    enter id:<input type="text" data-bind="value:id" />
    {{#if:id}}
    <ul>
        {{#nodeValue:id}}
        <li>The value is......{{$nodeValue().Value}}</li>
        <li>The Uom is......{{$nodeValue().Uom}}</li>
        <li>The attribute data is......{{$nodeValue().AttributeData}}</li>
        <li>The error message is......{{$nodeValue().ErrorMessage}}</li>
        {{/nodeValue}}
    </ul>
    {{/if}}
</div>

Implement an interface to make your own data source

    public interface IDeviceInterface: IDisposable
    {
        IEnumerable<MonitoredValue> Read(IEnumerable<Node> values);
        IEnumerable<MonitoredValue> Write(IEnumerable<WriteValue> values);
        IDeviceInterface SetDevice(Device device);
        void Subscribe(IEnumerable<Node> nodes);
        void Unsubscribe(IEnumerable<Node> nodes);
        Action<string, object, object, string> Changed { get; set; }
    }

and plug it in..

DeviceInterfacers.Add<OpcUADeviceInterface>("opc-ua");

Updaters are fired when subscribed to data changes

    Updaters.Add(async (id, mv) => await HubContext.Clients.Group(id.ToString()).UpdateDataValue(mv));

SiGyl.Opc.SelfHost

Self hosted server converting OPC to web sockets and web api calls for use by browsers and other clients

example startup.cs

using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Microsoft.Owin.Cors;
using Owin;
using SiGyl.Opc.Base;
using SiGyl.Opc.Base.Statuses;
using SiGyl.Opc.DeviceInterfacers.Local; 
using SiGyl.Opc.DeviceInterfacers.OpcLabs;
using SiGyl.Opc.Hubs.SignalR;
using System.Web.Http;
using System.Web.Http.Cors;
using XSockets.Core.Common.Socket;
using XSockets.Owin.Host;
using XSockets.Plugin.Framework;

[assembly: OwinStartup(typeof(SiGyl.Opc.SelfHost.Startup))]

namespace SiGyl.Opc.SelfHost
{
public class Startup
{
    // This code configures Web API. The Startup class is specified as a type
    // parameter in the WebApp.Start method.
    public void Configuration(IAppBuilder app)
    {
        // Branch the pipeline here for requests that start with "/signalr"
        app.Map("/signalr", map =>
        {
            // Setup the CORS middleware to run before SignalR.
            // By default this will allow all origins. You can
            // configure the set of origins and/or http verbs by
            // providing a cors options with a different policy.
            map.UseCors(CorsOptions.AllowAll);
            var hubConfiguration = new HubConfiguration
            {
                // You can enable JSONP by uncommenting line below.
                // JSONP requests are insecure but some older browsers (and some
                // versions of IE) require JSONP to work cross domain
                // EnableJSONP = true
            };
            // Run the SignalR pipeline. We're not using MapSignalR
            // since this branch already runs under the "/signalr"
            // path.
            map.RunSignalR(hubConfiguration);
        });

        // Configure Web API for self-host.
        HttpConfiguration config = new HttpConfiguration();

        config.MapHttpAttributeRoutes();
        config.EnableCors(new EnableCorsAttribute("*", "*", "*"));

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{zone}/{id}",
            defaults: new { zone = RouteParameter.Optional, id = RouteParameter.Optional }
        );

        app.UseWebApi(config);

        app.UseXSockets(true);
        Ioc.Standard();
        Ioc.Add<LocalDeviceInterface>("local");
        Ioc.Add<OpcUADeviceInterface>("opc-ua");
        Ioc.Add<OpcDADeviceInterface>("opc-da");
        Ioc.Build();

        var container = Composable.GetExport<IXSocketServerContainer>();
        container.Start();

        Status.AddStatus(new SiGyl.Opc.SignalR.Status { StatusHub = GlobalHost.ConnectionManager.GetHubContext<StatusHub>() });
        Status.AddStatus(new ConsoleStatus());
        //Status.AddStatus(new SiGyl.Opc.XSockets.Status { Publish = StatusController.Publish });
    }
}

}

Example Program.cs

using Microsoft.Owin.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SiGyl.Opc.SelfHost
{
class Program
{
    static void Main()
    {
        string baseAddress = "http://localhost:4501/";

        // Start OWIN host 
        using (WebApp.Start<Startup>(url: baseAddress))
        {
            Console.WriteLine("I am running on port 4501 press enter to finish");
            Console.ReadLine();
        }


    } 

}
}