# Tuesday, September 07, 2010
CSWorks provides a mechanism to support LiveData, Alarming and Historical data access authorization, but does not have access rights management functionality. Companies that deploy web-based solutions usually have some access management infrastructure in place, which is either based on Active Directory or integrates with some third-party technologies. And in most cases, IT managers in these companies do not like the idea of having yet another piece of security infrastructure that can be used for SCADA-related authentication tasks only. It's just too much hassle: extra support, one more set of user names and passwords to maintain, extra security risks.

This is why we do not offer our own access right management subsystem with CSWorks - we want to let IT managers choose the right one. We designed CSWorks in a way it can be integrated with existing security solutions. It's up to the application developer team how CSWorks-powered ASP.NET application authenticates a user and what screens are available to the authenticated user. CSWorks can only enforce some restrictions on data access when a CSWorks-powered client application accesses data - LiveData Alarming, or Historical (see CSWorks documentation for details).

If you are new to the world of the web-based access rights management systems, you probably need something to start with. I would recommend downloading a few products available on the market and getting familiar with them. PortSight SecureAccess and Atlassian Crowd are good candidates: they both support Active Directory integration, both are .NET friendly, both are mature products, both provide samples for .NET developers. If you decide to use such a product for your CSWorks solution, your application should perform the following tasks.
  1. User authentication. Performed by the selected access right management solution either through API or through a separate web page.
  2. CSWorks web service access authorization. Authorization information is stored in the ASP.NET session state, see CSWorks documentation for details.
  3. ASP.NET page access authorization. Your ASP.NET application should provides access only to the pages that are available to the authenticated user. This can be done by using access right management solution API (direct .NET calls or web service-based).
  4. Silverlight page access authorization. Your Silverlight client application should provides access only to the pages that are available to the authenticated user. This can be done by a variety of methods: web service calls from the client applications or passing startup parameters to the Silverlight engine when starting client application.
Of course, there is a learning curve involved in some cases. Yes, third-party (or custom developed) software is involved. The benefits outweigh the risks though - customers get a robust solution that works in a predictable way and re-uses existing security infrastructure.

Sergey Sorokin   Tuesday, September 07, 2010 11:06:29 AM (Pacific Daylight Time, UTC-07:00)  #     |  Comments [0]  | 
# Monday, April 19, 2010

Resizable controls - what's the problem?

To save HMI screen space, application developers may want to make some controls resizable. Applying ScaleTransform is not a problem and is a good solution in many cases. See Pipes and Tanks Demo for example - it uses ScaleTransform and redraws screen content when a user changes browser window size.

Unfortunately, ScaleTransform is not an optimal solution when dealing with complex UI elements, especially those containing some amount of text - some pieces may look ugly, some may become too small to be useful. The only solution is to make complex controls able to react to the 'SizeChanged' event and recalculate internal layout at runtime. Latest version of Alarm Summary and Trend Control can do that, and this post shows how application developers can use this functionality.

We will need a container control that lets user change its size, and a piece of code that passes the changes to CSWorks controls. You can develop your own container control (there are a lot of examples available in the web) or use an existing third-party container control for that. I will use RadWindow from Telerik in this example - it serves the purpose quite well.

Resizable Alarm Demo

1. Download Rad Controls for Silverlight trial package from www.telerik.com (DLLs only).
2. Unzip downloaded archive to "C:\Program Files\CSWorks\Demo\Src\tps\Telerik". Telerik DLLs will be unpacked to "C:\Program Files\CSWorks\Demo\Src\tps\Telerik\Binaries\Silverlight\".
3. Open Alarm Demo project ("C:\Program Files\CSWorks\Demo\Src\AlarmDemo\") in Visual Studio.
4. We will use RadWindow control implemented in Telerik.Windows.Controls.Navigation.dll. Add Telerik.Windows.Controls.Navigation.dll and Telerik.Windows.Controls.dll to the reference list for Alarm Demo project.
5. Open Page.xaml file. Add 'telerik' namespace to the UserControl element:

<UserControl ...
  xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation"
... >


6. Replace control content with a grid that contains RawWindow that contains CSWorks Alarm Summary, and add SizeChanged event handler for RadWindow:

<Grid>
  <telerik:RadWindow x:Name="radWindow" SizeChanged="OnSizeChanged">
    <telerik:RadWindow.Header>
      <TextBlock Text="Alarm Demo"/>
    </telerik:RadWindow.Header>
    <alarm:AlarmSummary ... />
  </telerik:RadWindow>
</Grid>


7. Open Page.xaml.cs file, implement SizeChanged event handler that adjusts AlarmSummary height and width when RadWindow size is changed: 

private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
  GeneralTransform gtGlobal = alarmSummary.TransformToVisual(radWindow);
  Point leftTopGlobal = gtGlobal.Transform(new Point(0, 0));

  alarmSummary.Height = radWindow.Height - radWindow.BorderThickness.Bottom - leftTopGlobal.Y - 4.0;
  alarmSummary.Width = radWindow.Width - leftTopGlobal.X * 2;
}


8. Update Loaded event handler so RadWindow shows itself after page is loaded:

private void Page_Loaded(object sender, RoutedEventArgs e)
{
  ...
  radWindow.Show();
}


9. Rebuild the project and run Alarm Demo from Start Menu. Resize RadWindow and watch Alarm Summary changing its layout:

Resizable Trend

You can do the same to CSWorks Trend control.

1. Open Trend Demo project ("C:\Program Files\CSWorks\Demo\Src\TrendDemo\TrendDemo.Sample.csproj")
2. Add Telerik.Windows.Controls.Navigation.dll and Telerik.Windows.Controls.dll to the reference list.
3. Open MainPage.xaml file. Add 'telerik' namespace as shown above.
4. Change xaml so RadWindow contains TrendControl:

<Grid>
  <telerik:RadWindow x:Name="radWindow" SizeChanged="OnSizeChanged">
    <telerik:RadWindow.Header>
      <TextBlock Text="Trend Demo"/>
    </telerik:RadWindow.Header>
    <t:Trend ...>
      ...
    </t:Trend>
  </telerik:RadWindow>
</Grid>


5. Open MainPage.xanl.cs. Add OnSizeChanged handler:

private void OnSizeChanged(object sender, SizeChangedEventArgs e)
{
  GeneralTransform gtGlobal = _demoTrend.TransformToVisual(radWindow);
  Point leftTopGlobal = gtGlobal.Transform(new Point(0, 0));

  _demoTrend.Height = radWindow.Height - radWindow.BorderThickness.Bottom - leftTopGlobal.Y - 4.0;
  _demoTrend.Width = radWindow.Width - leftTopGlobal.X * 2;
}


6. Show RadWindow on startup:

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
  ...
  radWindow.Show();
}


7. Rebuild the project and run Trend Demo from Start Menu. Resize RadWindow and watch Trend control changing its layout: 


Sergey Sorokin   Monday, April 19, 2010 2:11:23 PM (Pacific Daylight Time, UTC-07:00)  #     |  Comments [0]  | 
# Monday, March 15, 2010

CSWorks client framework is all about third-party UI components. As of this writing, all major Silverlight component providers have come up with their versions of the Gauge control. In this example, I will show how you can integrate Telerik and/or ComponentOne gauge controls into CSWorks Pipes and Tanks Demo application. The result will look like this:



Here are the steps to make it work.

1. Download Telerik Silverlight controls (dlls only) and ComponentOne Studio Trial Package for Silverlight.
2. Create a folder for third-party controls - C:\Program Files\CSWorks\ThirdParty.
3. Unpack downloaded Telerik archive and install ComponentOne package.
4. Copy Telerik assemblies (Telerik.Windows.Controls.Gauge.dll, Telerik.Windows.Controls.dll, Telerik.Windows.Data.dll) and ComponentOne assemblies (C1.Silverlight.dll, C1.Silverlight.Gauge.dll) to ThirdParty folder.
5. Open C:\Program Files\CSWorks\Demo\Src\PipesAndTanksDemo\PipesAndTanksDemo.Sample.csproj in Visual Studio.
6. Add all copied third party assemblies to the project reference list.
7. Open Page.xaml and add third-party namespaces to the namespace list:

<UserControl x:Class="CSWorks.Client.PipesAndTanksDemo.Page"
  ...
  xmlns:tcontrol="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Gauge"
  xmlns:tgauge="clr-namespace:Telerik.Windows.Controls.Gauges;assembly=Telerik.Windows.Controls.Gauge"
  xmlns:c1gauge="clr-namespace:C1.Silverlight.Gauge;assembly=C1.Silverlight.Gauge"

  ...>


8. Add gauge controls to the page and bind them to LeftPumpSpeed and RightPumpSpeed data items:

<controls:TabItem Header="HMI Controls View">
    <Canvas>
        ...
        <Grid ...>
            ...
            <Border ...>
              ...
            </Border>

            <!-- Telerik Gauge for left pump -->
            <Border Grid.Row="1" Grid.Column="5" Grid.RowSpan="1" Grid.ColumnSpan="3" Background="White" BorderBrush="Black" BorderThickness="1" CornerRadius="5" Padding="5,0,5,0" Margin="0,10,0,-10">
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="Telerik Gauge" Foreground="Black" FontSize="8" HorizontalAlignment="Center"/>
                    <tcontrol:RadGauge x:Name="radGauge" VerticalAlignment="Bottom" >
                        <tgauge:RadialGauge  >
                            <tgauge:RadialScale Min="0" Max="200" LabelRotationMode="None" FontSize="7">
                                <tgauge:RadialScale.Label>
                                    <tgauge:LabelProperties FontSize="4.5"/>
                                </tgauge:RadialScale.Label>
                                <tgauge:RangeList>
                                    <tgauge:RadialRange Min="0" Max="100" StartWidth="0.05" EndWidth="0.05" Background="Green"/>
                                    <tgauge:RadialRange Min="100" Max="160" StartWidth="0.05" EndWidth="0.05" Background="Orange"/>
                                    <tgauge:RadialRange Min="160" Max="200" StartWidth="0.05" EndWidth="0.05" Background="Red" />
                                </tgauge:RangeList>
                                <tgauge:IndicatorList>
                                    <tgauge:Needle Value="{Binding Value, Mode=OneWay, Source={StaticResource LeftPumpSpeed}}"/>
                                </tgauge:IndicatorList>
                            </tgauge:RadialScale>
                        </tgauge:RadialGauge>
                    </tcontrol:RadGauge>
                    <TextBlock Text="rpm" Foreground="White" FontSize="7" HorizontalAlignment="Center" VerticalAlignment="Bottom"  Margin="0,-30,0,30"/>
                </StackPanel>
            </Border>

            <!-- ComponentOne Gauge for right pump -->
            <Border Grid.Row="1" Grid.Column="9" Grid.RowSpan="1" Grid.ColumnSpan="3" Background="White" BorderBrush="Black" BorderThickness="1" CornerRadius="5" Padding="5,0,5,0" Margin="0,10,0,-10">
                <StackPanel Orientation="Vertical">
                    <TextBlock Text="C1 Gauge" Foreground="Black" FontSize="8" HorizontalAlignment="Center"/>
                    <c1gauge:C1RadialGauge  Minimum="0" Maximum="200" Value="{Binding Value, Mode=OneWay, Source={StaticResource RightPumpSpeed}}">
                        <c1gauge:C1GaugeLabel Interval="20" Foreground="Black" Format="#" FontSize="6" FontWeight="200" Location="0.85"/>
                        <c1gauge:C1GaugeRange From="0" To="100"  Fill="Green" Location="0.45"/>
                        <c1gauge:C1GaugeRange From="100" To="160"  Fill="Orange" Location="0.45"/>
                        <c1gauge:C1GaugeRange From="160" To="200"  Fill="Red" Location="0.45"/>
                        <c1gauge:C1GaugeMark Interval="20" />
                    </c1gauge:C1RadialGauge>
                    <TextBlock Text="rpm" Foreground="Black" FontSize="7" HorizontalAlignment="Center" VerticalAlignment="Bottom"  Margin="0,-30,0,30"/>
                </StackPanel>
            </Border>


            <TextBlock Text="All UI elements ..." .../>
          </Grid>
          ...
    </Canvas>
</controls:TabItem>


9. Build the project and start Pipes and Tanks Demo from your start menu. Enjoy professional-looking controls in action.

Sergey Sorokin   Monday, March 15, 2010 9:47:19 AM (Pacific Standard Time, UTC-08:00)  #     |  Comments [0]  |