Compare commits

..

27 Commits

Author SHA1 Message Date
Andrew Welker
9a324191d8 adds builds repo push jobs to master.yml 2020-03-26 11:32:53 -06:00
Andrew Welker
83298bb06a adds delete step to push to public repo 2020-03-26 10:07:43 -06:00
Andrew Welker
f6ef7017a2 Merge pull request #75 from PepperDash/feature/rework-plugin-loading-process-to-avoid-assembly-conflicts
Feature/rework plugin loading process to avoid assembly conflicts
2020-03-26 08:09:43 -06:00
Neil Dorin
1418e8f8c6 New PluginLoader class fully tested and functional 2020-03-25 21:25:56 -06:00
Neil Dorin
d097cfe51b Merge pull request #74 from PepperDash/feature/update-systemmonitorcontroller
Feature/update systemmonitorcontroller
2020-03-25 17:26:06 -06:00
Andrew Welker
88ea297f16 fixes parameter for Copy-Item 2020-03-25 17:05:39 -06:00
Andrew Welker
63feaac9bd fixes workflow remove step 2020-03-25 16:49:37 -06:00
Andrew Welker
c5f0bff133 adds specific file types to workflow to delete from builds repo 2020-03-25 16:23:54 -06:00
Andrew Welker
bcfd90204b adds step to copy files to root 2020-03-25 15:46:09 -06:00
Andrew Welker
475be152a7 adds debug info for ethernet information and fixes issue incrementing joins correctly 2020-03-25 15:40:29 -06:00
Andrew Welker
534110cfbf updates XML comments for bool & string feedbacks 2020-03-25 15:07:47 -06:00
Andrew Welker
cbe96dbed9 Adds XML comments to constructors for Int, String, and Bool Feedbacks 2020-03-25 15:07:47 -06:00
Andrew Welker
e2fe8834c5 adds Uptime and LastBoot console parsing and reporting
* refactored ProgramInfo routine to not send console commands for unregistered or stopped programs and inverted some if statements
2020-03-25 15:07:47 -06:00
Andrew Welker
93e542befd adds bridging for all ethernet parameters 2020-03-25 15:07:47 -06:00
Andrew Welker
3852617270 adds DhcpEnabled feedback to SystemMonitor 2020-03-25 15:07:47 -06:00
Andrew Welker
d7a04e202b adds logic to get required parameters using built-in Crestron classes 2020-03-25 15:07:46 -06:00
Andrew Welker
abd6ab121e adding logic to get the requested data 2020-03-25 15:07:46 -06:00
Andrew Welker
0c274015dd created new feedback properties and intialized them 2020-03-25 15:07:46 -06:00
Andrew Welker
ffc0f8f58e cleans up formatting 2020-03-25 15:07:46 -06:00
Andrew Welker
c47f7ba7e3 code cleanup to match new standars 2020-03-25 15:07:46 -06:00
Neil Dorin
733dbf9bd7 Moves all plugin logic to new PluginLoader static class 2020-03-25 15:04:44 -06:00
Neil Dorin
58c3c4fac7 Merge pull request #72 from PepperDash/feature/add-docker-build-action
adds logic to rename .cpz to add version...
2020-03-24 17:06:45 -06:00
Andrew Welker
82ddd40953 adds logic to rename .cpz to add version...
...& points to different repo for create release action
2020-03-24 16:55:20 -06:00
Neil Dorin
e6fb9cd1eb moving to updated informational version and setting up to unzip plugin cplz files into a folder one at a time before loading 2020-03-24 16:20:42 -06:00
Neil Dorin
830b83f99f Merge remote-tracking branch 'origin/development' into feature/ecs-1257 2020-03-23 14:55:00 -06:00
Neil Dorin
a2ebeab839 Merge branch 'release/v1.4.33' into feature/ecs-1257
# Conflicts:
#	PepperDashEssentials/ControlSystem.cs
#	essentials-framework/Essentials Core/PepperDashEssentialsBase/Global/Global.cs
2020-02-26 10:35:56 -07:00
Neil Dorin
d81bcfba9a Attempts to address the issue of duplicate assembly .dlls being loaded via plugins 2020-02-05 17:13:27 -07:00
18 changed files with 1104 additions and 609 deletions

View File

@@ -26,7 +26,7 @@ Get-ChildItem -recurse -Path "$($Env:GITHUB_WORKSPACE)" -include "*.clz", "*.cpz
} | Copy-Item -Destination ($destination) -Force
Write-Host "Getting matching files..."
# Get any files from the output folder that match the following extensions
Get-ChildItem -Path $destination | Where-Object {($_.Extension -eq ".clz") -or ($_.Extension -eq ".cpz" -or ($_.Extension -eq ".cplz"))} | ForEach-Object {
Get-ChildItem -Path $destination | Where-Object { ($_.Extension -eq ".clz") -or ($_.Extension -eq ".cpz" -or ($_.Extension -eq ".cplz")) } | ForEach-Object {
# Replace the extensions with dll and xml and create an array
$filenames = @($($_ -replace "cpz|clz|cplz", "dll"), $($_ -replace "cpz|clz|cplz", "xml"))
Write-Host "Filenames:"
@@ -36,6 +36,8 @@ Get-ChildItem -Path $destination | Where-Object {($_.Extension -eq ".clz") -or (
Get-ChildItem -Recurse -Path "$($Env:GITHUB_WORKSPACE)" -include $filenames | Copy-Item -Destination ($destination) -Force
}
}
Get-ChildItem -Path $destination\*.cpz | Rename-Item -NewName { "$($_.BaseName)-$($Env:VERSION)$($_.Extension)" }
Compress-Archive -Path $destination -DestinationPath "$($Env:GITHUB_WORKSPACE)\$($Env:SOLUTION_FILE)-$($Env:VERSION).zip" -Force
Write-Host "Output Contents post Zip"
Get-ChildItem -Path $destination

View File

@@ -10,7 +10,7 @@ on:
env:
# solution path doesn't need slashes unless there it is multiple folders deep
# solution name does not include extension. .sln is assumed
# solution name does not include extension. .sln is assumed
SOLUTION_PATH: PepperDashEssentials
SOLUTION_FILE: PepperDashEssentials
# Do not edit this, we're just creating it here
@@ -78,7 +78,8 @@ jobs:
# Create the release on the source repo
- name: Create Release
id: create_release
uses: actions/create-release@v1
# using contributor's version to allow for pointing at the right commit
uses: fleskesvor/create-release@feature/support-target-commitish
with:
tag_name: ${{ env.VERSION }}
release_name: ${{ env.VERSION }}
@@ -143,6 +144,12 @@ jobs:
Remove-Item -Path .\*.zip
- name: Check directory again
run: Get-ChildItem ./
# Copy Contents of output folder to root directory
- name: Copy Files to root & delete output directory
run: |
Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz")
Get-ChildItem -Path .\output\* | Copy-Item -Destination .\
Remove-Item -Path .\output -Recurse
# Commits the build output to the branch and tags it with the version
- name: Commit build output and tag the commit
shell: powershell
@@ -214,6 +221,12 @@ jobs:
Remove-Item -Path .\*.zip
- name: Check directory again
run: Get-ChildItem ./
# Copy Contents of output folder to root directory
- name: Copy Files to root & delete output directory
run: |
Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz")
Get-ChildItem -Path .\output\* | Copy-Item -Destination .\
Remove-Item -Path .\output -Recurse
# Commits the build output to the branch and tags it with the version
- name: Commit build output and tag the commit
shell: powershell

View File

@@ -56,21 +56,11 @@ jobs:
- name: Zip Build Output
shell: powershell
run: ./.github/scripts/ZipBuildOutput.ps1
# Write the version to a file to be consumed by the push jobs
- name: Write Version
run: Write-Output "$($Env:VERSION)" | Out-File -FilePath "$($Env:GITHUB_HOME)\output\version.txt"
# Upload the build output as an artifact
- name: Upload Build Output
uses: actions/upload-artifact@v1
with:
name: Build
path: ./${{ env.SOLUTION_FILE}}-${{ env.VERSION}}.zip
# Upload the Version file as an artifact
- name: Upload version.txt
uses: actions/upload-artifact@v1
with:
name: Version
path: ${{env.GITHUB_HOME}}\output\version.txt
# Upload the build package to the release
- name: Upload Release Package
id: upload_release
@@ -82,6 +72,7 @@ jobs:
asset_content_type: application/zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# This step always runs and pushes the build to the internal build rep
Internal_Push_Output:
needs: Build_Project
runs-on: windows-latest
@@ -111,8 +102,8 @@ jobs:
Remove-Item -Path ./Version/version.txt
Remove-Item -Path ./Version
# Checkout/Create the branch
- name: Checkout Master branch
run: git checkout master
- name: Create new branch
run: git checkout -b $($Env:GITHUB_REF -replace "refs/heads/")
# Download the build output into the repo
- name: Download Build output
uses: actions/download-artifact@v1
@@ -128,7 +119,7 @@ jobs:
Remove-Item -Path .\*.zip
- name: Check directory again
run: Get-ChildItem ./
# Copy Contents of output folder to root directory
# Copy Contents of output folder to root directory
- name: Copy Files to root & delete output directory
run: |
Remove-Item -Path .\* -Include @("*.cpz","*.md","*.cplz","*.json","*.dll","*.clz")
@@ -148,7 +139,10 @@ jobs:
# Push the commit
- name: Push to Builds Repo
shell: powershell
run: git push -u origin master --force
run: |
$branch = $($Env:GITHUB_REF) -replace "refs/heads/"
Write-Host "Branch: $branch"
git push -u origin $($branch) --force
# Push the tags
- name: Push tags
run: git push --tags origin
@@ -158,6 +152,7 @@ jobs:
Public_Push_Output:
needs: Build_Project
runs-on: windows-latest
if: contains(github.ref, 'master') || contains(github.ref, 'release')
steps:
# Checkout the repo
- name: Checkout Builds Repo
@@ -185,7 +180,7 @@ jobs:
Remove-Item -Path ./Version
# Checkout/Create the branch
- name: Create new branch
run: git checkout -b master
run: git checkout -b $($Env:GITHUB_REF -replace "refs/heads/")
# Download the build output into the repo
- name: Download Build output
uses: actions/download-artifact@v1
@@ -221,7 +216,10 @@ jobs:
# Push the commit
- name: Push to Builds Repo
shell: powershell
run: git push -u origin master --force
run: |
$branch = $($Env:GITHUB_REF) -replace "refs/heads/"
Write-Host "Branch: $branch"
git push -u origin $($branch) --force
# Push the tags
- name: Push tags
run: git push --tags origin

View File

@@ -1,11 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Newtonsoft.Json;
using PepperDash.Core;
using PepperDash.Essentials.Core.Monitoring;
@@ -23,11 +17,11 @@ namespace PepperDash.Essentials.AppServer.Messengers
SysMon = sysMon;
SysMon.SystemMonitorPropertiesChanged += new EventHandler<EventArgs>(SysMon_SystemMonitorPropertiesChanged);
SysMon.SystemMonitorPropertiesChanged += SysMon_SystemMonitorPropertiesChanged;
foreach (var p in SysMon.ProgramStatusFeedbackCollection)
{
p.Value.ProgramInfoChanged += new EventHandler<ProgramInfoEventArgs>(ProgramInfoChanged);
p.Value.ProgramInfoChanged += ProgramInfoChanged;
}
CrestronConsole.AddNewConsoleCommand(s => SendFullStatusMessage(), "SendFullSysMonStatus", "Sends the full System Monitor Status", ConsoleAccessLevelEnum.AccessOperator);
@@ -72,18 +66,15 @@ namespace PepperDash.Essentials.AppServer.Messengers
Debug.Console(1, "Posting System Monitor Status Message.");
// This takes a while, launch a new thread
CrestronInvoke.BeginInvoke((o) =>
CrestronInvoke.BeginInvoke(o => PostStatusMessage(new
{
PostStatusMessage(new
{
timeZone = SysMon.TimeZoneFeedback.IntValue,
timeZoneName = SysMon.TimeZoneTextFeedback.StringValue,
ioControllerVersion = SysMon.IOControllerVersionFeedback.StringValue,
snmpVersion = SysMon.SnmpVersionFeedback.StringValue,
bacnetVersion = SysMon.BACnetAppVersionFeedback.StringValue,
controllerVersion = SysMon.ControllerVersionFeedback.StringValue
});
});
timeZone = SysMon.TimeZoneFeedback.IntValue,
timeZoneName = SysMon.TimeZoneTextFeedback.StringValue,
ioControllerVersion = SysMon.IoControllerVersionFeedback.StringValue,
snmpVersion = SysMon.SnmpVersionFeedback.StringValue,
bacnetVersion = SysMon.BaCnetAppVersionFeedback.StringValue,
controllerVersion = SysMon.ControllerVersionFeedback.StringValue
}));
}
protected override void CustomRegisterWithAppServer(MobileControlSystemController appServerController)

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials.Bridges
{
@@ -14,11 +9,21 @@ namespace PepperDash.Essentials.Bridges
/// </summary>
public uint ProgramStartJoin { get; set; }
/// <summary>
/// Offset to indicate where the range of iterated Ethernet joins will start
/// </summary>
public uint EthernetStartJoin { get; set; }
/// <summary>
/// Offset between each program join set
/// </summary>
public uint ProgramOffsetJoin { get; set; }
/// <summary>
/// Offset between each Ethernet Interface join set
/// </summary>
public uint EthernetOffsetJoin { get; set; }
#region Digitals
/// <summary>
/// Range Sets and reports whether the corresponding program slot is started
@@ -87,6 +92,68 @@ namespace PepperDash.Essentials.Bridges
/// Serialized JSON output that aggregates the program info of the corresponding program
/// </summary>
public uint AggregatedProgramInfo { get; set; }
/// <summary>
/// Reports the controller serial number
/// </summary>
public uint SerialNumber { get; set; }
/// <summary>
/// Reports the controller model
/// </summary>
public uint Model { get; set; }
/// <summary>
/// Reports the Host name set on the corresponding interface
/// </summary>
public uint HostName { get; set; }
/// <summary>
/// Reports the Current IP address set on the corresponding interface. If DHCP is enabled, this will be the DHCP assigned address.
/// </summary>
public uint CurrentIpAddress { get; set; }
/// <summary>
/// Reporst the Current Default Gateway set on the corresponding interface. If DHCP is enabled, this will be the DHCP assigned gateway
/// </summary>
public uint CurrentDefaultGateway { get; set; }
/// <summary>
/// Reports the Current Subnet Mask set on the corresponding interface. If DHCP is enabled, this will be the DHCP assigned subnet mask
/// </summary>
public uint CurrentSubnetMask { get; set; }
/// <summary>
/// Reports the Static IP address set on the corresponding interface. If DHCP is disabled, this will match the Current IP address
/// </summary>
public uint StaticIpAddress { get; set; }
/// <summary>
/// Reporst the Static Default Gateway set on the corresponding interface. If DHCP is disabled, this will match the Current gateway
/// </summary>
public uint StaticDefaultGateway { get; set; }
/// <summary>
/// Reports the Current Subnet Mask set on the corresponding interface. If DHCP is enabled, this will be the DHCP assigned subnet mask
/// </summary>
public uint StaticSubnetMask { get; set; }
/// <summary>
/// Reports the current DomainFeedback on the corresponding interface
/// </summary>
public uint Domain { get; set; }
/// <summary>
/// Reports the current DNS Servers on the corresponding interface
/// </summary>
public uint DnsServer { get; set; }
/// <summary>
/// Reports the MAC Address of the corresponding interface
/// </summary>
public uint MacAddress { get; set; }
/// <summary>
/// Reports the DHCP Status of the corresponding interface
/// </summary>
public uint DhcpStatus { get; set; }
/// <summary>
/// Reports the current uptime. Updated in 5 minute intervals.
/// </summary>
public uint Uptime { get; set; }
/// <summary>
/// Reports the date of the last boot
/// </summary>
public uint LastBoot { get; set; }
#endregion
public SystemMonitorJoinMap()
@@ -98,6 +165,10 @@ namespace PepperDash.Essentials.Bridges
SnmpAppVersion = 3;
BACnetAppVersion = 4;
ControllerVersion = 5;
SerialNumber = 6;
Model = 7;
Uptime = 8;
LastBoot = 9;
ProgramStartJoin = 10;
@@ -115,6 +186,23 @@ namespace PepperDash.Essentials.Bridges
ProgramCrestronDatabaseVersion = 3;
ProgramEnvironmentVersion = 4;
AggregatedProgramInfo = 5;
EthernetStartJoin = 75;
EthernetOffsetJoin = 15;
// Offset in groups of 15
HostName = 1;
CurrentIpAddress = 2;
CurrentSubnetMask = 3;
CurrentDefaultGateway = 4;
StaticIpAddress = 5;
StaticSubnetMask = 6;
StaticDefaultGateway = 7;
Domain = 8;
DnsServer = 9;
MacAddress = 10;
DhcpStatus = 11;
}
public override void OffsetJoinNumbers(uint joinStart)
@@ -131,6 +219,7 @@ namespace PepperDash.Essentials.Bridges
// Sets the initial join value where the iterated program joins will begin
ProgramStartJoin = ProgramStartJoin + joinOffset;
EthernetStartJoin = EthernetStartJoin + joinOffset;
}
}
}

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.Diagnostics;
using PepperDash.Core;
using PepperDash.Essentials.Core;
@@ -17,7 +12,7 @@ namespace PepperDash.Essentials.Bridges
{
public static void LinkToApi(this SystemMonitorController systemMonitorController, BasicTriList trilist, uint joinStart, string joinMapKey)
{
SystemMonitorJoinMap joinMap = new SystemMonitorJoinMap();
var joinMap = new SystemMonitorJoinMap();
var joinMapSerialized = JoinMapHelper.GetJoinMapForDevice(joinMapKey);
@@ -30,36 +25,71 @@ namespace PepperDash.Essentials.Bridges
Debug.Console(2, systemMonitorController, "Linking API starting at join: {0}", joinStart);
systemMonitorController.TimeZoneFeedback.LinkInputSig(trilist.UShortInput[joinMap.TimeZone]);
//trilist.SetUShortSigAction(joinMap.TimeZone, new Action<ushort>(u => systemMonitorController.SetTimeZone(u)));
systemMonitorController.TimeZoneTextFeedback.LinkInputSig(trilist.StringInput[joinMap.TimeZoneName]);
systemMonitorController.IOControllerVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.IOControllerVersion]);
systemMonitorController.IoControllerVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.IOControllerVersion]);
systemMonitorController.SnmpVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.SnmpAppVersion]);
systemMonitorController.BACnetAppVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.BACnetAppVersion]);
systemMonitorController.BaCnetAppVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.BACnetAppVersion]);
systemMonitorController.ControllerVersionFeedback.LinkInputSig(trilist.StringInput[joinMap.ControllerVersion]);
systemMonitorController.SerialNumberFeedback.LinkInputSig(trilist.StringInput[joinMap.SerialNumber]);
systemMonitorController.ModelFeedback.LinkInputSig(trilist.StringInput[joinMap.Model]);
systemMonitorController.UptimeFeedback.LinkInputSig(trilist.StringInput[joinMap.Uptime]);
systemMonitorController.LastStartFeedback.LinkInputSig(trilist.StringInput[joinMap.LastBoot]);
// iterate the program status feedback collection and map all the joins
LinkProgramInfoJoins(systemMonitorController, trilist, joinMap);
LinkEthernetInfoJoins(systemMonitorController, trilist, joinMap);
}
private static void LinkEthernetInfoJoins(SystemMonitorController systemMonitorController, BasicTriList trilist, SystemMonitorJoinMap joinMap)
{
var ethernetSlotJoinStart = joinMap.EthernetStartJoin;
foreach (var fb in systemMonitorController.EthernetStatusFeedbackCollection)
{
fb.Value.CurrentIpAddressFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.CurrentIpAddress]);
fb.Value.CurrentSubnetMaskFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.CurrentSubnetMask]);
fb.Value.CurrentDefaultGatewayFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.CurrentDefaultGateway]);
fb.Value.StaticIpAddressFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.StaticIpAddress]);
fb.Value.StaticSubnetMaskFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.StaticSubnetMask]);
fb.Value.StaticDefaultGatewayFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.StaticDefaultGateway]);
fb.Value.HostNameFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.HostName]);
fb.Value.MacAddressFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.MacAddress]);
fb.Value.DomainFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.Domain]);
fb.Value.DnsServerFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.DnsServer]);
fb.Value.DhcpStatusFeedback.LinkInputSig(trilist.StringInput[ethernetSlotJoinStart + joinMap.DhcpStatus]);
ethernetSlotJoinStart += joinMap.EthernetOffsetJoin;
}
}
private static void LinkProgramInfoJoins(SystemMonitorController systemMonitorController, BasicTriList trilist,
SystemMonitorJoinMap joinMap)
{
var programSlotJoinStart = joinMap.ProgramStartJoin;
foreach (var p in systemMonitorController.ProgramStatusFeedbackCollection)
{
var programNumber = p.Value.Program.Number;
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramStart, new Action<bool>
(b => SystemMonitor.ProgramCollection[programNumber].OperatingState = eProgramOperatingState.Start));
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramStart,
b => SystemMonitor.ProgramCollection[programNumber].OperatingState = eProgramOperatingState.Start);
p.Value.ProgramStartedFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramStart]);
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramStop, new Action<bool>
(b => SystemMonitor.ProgramCollection[programNumber].OperatingState = eProgramOperatingState.Stop));
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramStop,
b => SystemMonitor.ProgramCollection[programNumber].OperatingState = eProgramOperatingState.Stop);
p.Value.ProgramStoppedFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramStop]);
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramRegister, new Action<bool>
(b => SystemMonitor.ProgramCollection[programNumber].RegistrationState = eProgramRegistrationState.Register));
p.Value.ProgramRegisteredFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramRegister]);
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramRegister,
b => SystemMonitor.ProgramCollection[programNumber].RegistrationState = eProgramRegistrationState.Register);
p.Value.ProgramRegisteredFeedback.LinkInputSig(
trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramRegister]);
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramUnregister, new Action<bool>
(b => SystemMonitor.ProgramCollection[programNumber].RegistrationState = eProgramRegistrationState.Unregister));
p.Value.ProgramUnregisteredFeedback.LinkInputSig(trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramUnregister]);
trilist.SetBoolSigAction(programSlotJoinStart + joinMap.ProgramUnregister,
b => SystemMonitor.ProgramCollection[programNumber].RegistrationState = eProgramRegistrationState.Unregister);
p.Value.ProgramUnregisteredFeedback.LinkInputSig(
trilist.BooleanInput[programSlotJoinStart + joinMap.ProgramUnregister]);
p.Value.ProgramNameFeedback.LinkInputSig(trilist.StringInput[programSlotJoinStart + joinMap.ProgramName]);
p.Value.ProgramCompileTimeFeedback.LinkInputSig(

View File

@@ -25,6 +25,7 @@ namespace PepperDash.Essentials
{
HttpLogoServer LogoServer;
public ControlSystem()
: base()
{
@@ -46,6 +47,8 @@ namespace PepperDash.Essentials
ConsoleAccessLevelEnum.AccessOperator);
}
CrestronConsole.AddNewConsoleCommand(PluginLoader.ReportAssemblyVersions, "reportversions", "Reports the versions of the loaded assemblies", ConsoleAccessLevelEnum.AccessOperator);
// CrestronConsole.AddNewConsoleCommand(S => { ConfigWriter.WriteConfigFile(null); }, "writeconfig", "writes the current config to a file", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s =>
{
@@ -78,10 +81,12 @@ namespace PepperDash.Essentials
GoWithLoad();
}
/// <summary>
/// Determines if the program is running on a processor (appliance) or server (VC-4).
///
/// Sets Global.FilePathPrefix based on platform
/// Sets Global.FilePathPrefix and Global.ApplicationDirectoryPathPrefix based on platform
/// </summary>
public void DeterminePlatform()
{
@@ -108,7 +113,7 @@ namespace PepperDash.Essentials
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials v{0} on 3-series Appliance", Global.AssemblyVersion);
// Check if User/ProgramX exists
if (Directory.Exists(directoryPrefix + dirSeparator + "User"
if (Directory.Exists(Global.ApplicationDirectoryPathPrefix + dirSeparator + "User"
+ dirSeparator + string.Format("program{0}", InitialParametersClass.ApplicationNumber)))
{
Debug.Console(0, @"User/program{0} directory found", InitialParametersClass.ApplicationNumber);
@@ -158,11 +163,13 @@ namespace PepperDash.Essentials
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Starting Essentials load from configuration");
PluginLoader.AddProgramAssemblies();
var filesReady = SetupFilesystem();
if (filesReady)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Checking for plugins");
LoadPlugins();
PluginLoader.LoadPlugins();
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Folder structure verified. Loading config...");
if (!ConfigReader.LoadConfig2())
@@ -197,118 +204,7 @@ namespace PepperDash.Essentials
}
/// <summary>
/// Initial simple implementation. Reads user/programXX/plugins folder and
/// use
/// </summary>
void LoadPlugins()
{
var dir = Global.FilePathPrefix + "plugins";
if (Directory.Exists(dir))
{
// TODO Clear out or create localPlugins folder (maybe in program slot folder)
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Plugins directory found, checking for factory plugins");
var di = new DirectoryInfo(dir);
var zFiles = di.GetFiles("*.cplz");
foreach (var fi in zFiles)
{
Debug.Console(0, "Found cplz: {0}. Unzipping into plugins directory", fi.Name);
var result = CrestronZIP.Unzip(fi.FullName, di.FullName);
Debug.Console(0, "UnZip Result: {0}", result.ToString());
fi.Delete();
}
var files = di.GetFiles("*.dll");
Dictionary<string, Assembly> assyList = new Dictionary<string, Assembly>();
foreach (FileInfo fi in files)
{
// TODO COPY plugin to loadedPlugins folder
// TODO LOAD that loadedPlugins dll file
try
{
var assy = Assembly.LoadFrom(fi.FullName);
var ver = assy.GetName().Version;
var verStr = string.Format("{0}.{1}.{2}.{3}", ver.Major, ver.Minor, ver.Build, ver.Revision);
assyList.Add(fi.FullName, assy);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loaded plugin file '{0}', version {1}", fi.FullName, verStr);
}
catch
{
Debug.Console(2, "Assembly {0} is not a custom assembly", fi.FullName);
continue; //catching any load issues and continuing. There will be exceptions loading Crestron .dlls from the cplz Probably should do something different here
}
}
foreach (var assy in assyList)
{
// iteratate this assembly's classes, looking for "LoadPlugin()" methods
try
{
var types = assy.Value.GetTypes();
foreach (var type in types)
{
try
{
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
var loadPlugin = methods.FirstOrDefault(m => m.Name.Equals("LoadPlugin"));
if (loadPlugin != null)
{
Debug.Console(2, "LoadPlugin method found in {0}", type.Name);
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static);
var minimumVersion = fields.FirstOrDefault(p => p.Name.Equals("MinimumEssentialsFrameworkVersion"));
if (minimumVersion != null)
{
Debug.Console(2, "MinimumEssentialsFrameworkVersion found");
var minimumVersionString = minimumVersion.GetValue(null) as string;
if (!string.IsNullOrEmpty(minimumVersionString))
{
var passed = Global.IsRunningMinimumVersionOrHigher(minimumVersionString);
if (!passed)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Plugin indicates minimum Essentials version {0}. Dependency check failed. Skipping Plugin", minimumVersionString);
continue;
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Passed plugin passed dependency check (required version {0})", minimumVersionString);
}
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Warning, "MinimumEssentialsFrameworkVersion found but not set. Loading plugin, but your mileage may vary.");
}
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Warning, "MinimumEssentialsFrameworkVersion not found. Loading plugin, but your mileage may vary.");
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Adding plugin: {0}", assy.Key);
loadPlugin.Invoke(null, null);
}
}
catch
{
Debug.Console(2, "Load Plugin not found. {0} is not a plugin assembly", assy.Value.FullName);
continue;
}
}
}
catch
{
Debug.Console(2, "Assembly {0} is not a custom assembly. Types cannot be loaded.", assy.Value.FullName);
continue;
}
}
// plugin dll will be loaded. Any classes in plugin should have a static constructor
// that registers that class with the Core.DeviceFactory
}
}
/// <summary>
/// Verifies filesystem is set up. IR, SGD, and programX folders

View File

@@ -1,266 +0,0 @@
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using Crestron.SimplSharp;
//using Crestron.SimplSharp.CrestronIO;
//using Crestron.SimplSharp.Net.Http;
//using Newtonsoft.Json;
//using Newtonsoft.Json.Linq;
//using PepperDash.Essentials.Core;
//using PepperDash.Essentials.Core.Http;
//using PepperDash.Core;
//namespace PepperDash.Essentials
//{
// public class EssentialsHttpApiHandler
// {
// string ConfigPath;
// string PresetsPathPrefix;
// EssentialsHttpServer Server;
// /// <summary>
// ///
// /// </summary>
// /// <param name="server">HTTP server to attach to</param>
// /// <param name="configPath">The full path to configuration file</param>
// /// <param name="presetsListPath">The folder prefix for the presets path, eq "\HTML\presets\"</param>
// public EssentialsHttpApiHandler(EssentialsHttpServer server, string configPath, string presetsPathPrefix)
// {
// if (server == null) throw new ArgumentNullException("server");
// Server = server;
// ConfigPath = configPath;
// PresetsPathPrefix = presetsPathPrefix;
// server.ApiRequest += Server_ApiRequest;
// }
// void Server_ApiRequest(object sender, Crestron.SimplSharp.Net.Http.OnHttpRequestArgs args)
// {
// try
// {
// var path = args.Request.Path.ToLower();
// if (path == "/api/config")
// HandleApiConfig(args);
// else if (path.StartsWith("/api/presetslist/"))
// HandleApiPresetsList(args);
// else if (path == "/api/presetslists")
// HandleApiGetPresetsLists(args.Request, args.Response);
// else
// {
// args.Response.Code = 404;
// return;
// }
// args.Response.Header.SetHeaderValue("Access-Control-Allow-Origin", "*");
// args.Response.Header.SetHeaderValue("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS");
// }
// catch (Exception e)
// {
// Debug.Console(1, "Uncaught HTTP server error: \n{0}", e);
// args.Response.Code = 500;
// }
// }
// /// <summary>
// /// GET will return the running configuration. POST will attempt to take in a new config
// /// and restart the program.
// /// </summary>
// void HandleApiConfig(OnHttpRequestArgs args)
// {
// var request = args.Request;
// if (request.Header.RequestType == "GET")
// {
// if (File.Exists(ConfigPath))
// {
// Debug.Console(2, "Sending config:{0}", ConfigPath);
// args.Response.Header.ContentType = EssentialsHttpServer.GetContentType(new FileInfo(ConfigPath).Extension);
// args.Response.ContentStream = new FileStream(ConfigPath, FileMode.Open, FileAccess.Read);
// }
// }
// else if (request.Header.RequestType == "POST")
// {
// Debug.Console(2, "Post type: '{0}'", request.Header.ContentType);
// // Make sure we're receiving at least good json
// Debug.Console(1, "Receving new config");
// if (GetContentStringJson(args) == null)
// return;
// //---------------------------- try to move these into common method
// // Move current file aside
// var bakPath = ConfigPath + ".bak";
// if (File.Exists(bakPath))
// File.Delete(bakPath);
// File.Move(ConfigPath, bakPath);
// // Write the file
// using (FileStream fs = File.Open(ConfigPath, FileMode.OpenOrCreate))
// using (StreamWriter sw = new StreamWriter(fs))
// {
// try
// {
// sw.Write(args.Request.ContentString);
// }
// catch (Exception e)
// {
// string err = string.Format("Error writing received config file:\r{0}", e);
// CrestronConsole.PrintLine(err);
// ErrorLog.Warn(err);
// // Put file back
// File.Move(ConfigPath + ".bak", ConfigPath);
// args.Response.Code = 500;
// return;
// }
// }
// // If client says "yeah, restart" and has a good token
// // Restart program
// string consoleResponse = null;
// var restart = CrestronConsole.SendControlSystemCommand("progreset -p:" +
// InitialParametersClass.ApplicationNumber, ref consoleResponse);
// if (!restart) Debug.Console(0, "CAN'T DO THAT YO: {0}", consoleResponse);
// }
// }
// void HandleApiPresetsList(OnHttpRequestArgs args)
// {
// var listPath = PresetsPathPrefix + args.Request.Path.Remove(0, 17);
// Debug.Console(2, "Checking for preset list '{0}'", listPath);
// if (args.Request.Header.RequestType == "GET")
// {
// if (File.Exists(listPath))
// {
// Debug.Console(2, "Sending presets file:{0}", listPath);
// args.Response.Header.ContentType = EssentialsHttpServer.GetContentType(new FileInfo(listPath).Extension);
// args.Response.ContentStream = new FileStream(listPath, FileMode.Open, FileAccess.Read);
// }
// }
// else if (args.Request.Header.RequestType == "POST")
// {
// // Make sure we're receiving at least good json
// Debug.Console(1, "Receving new presets");
// if (GetContentStringJson(args) == null)
// return;
// //---------------------------- try to move these into common method
// // Move current file aside
// var bakPath = listPath + ".new";
// Debug.Console(2, "Moving presets file to {0}", bakPath);
// if(File.Exists(bakPath))
// File.Delete(bakPath);
// File.Move(listPath, bakPath);
// Debug.Console(2, "Writing new file");
// // Write the file
// using (FileStream fs = File.OpenWrite(listPath))
// using (StreamWriter sw = new StreamWriter(fs))
// {
// try
// {
// Debug.Console(2, "Writing {1}, {0} bytes", args.Request.ContentString.Length, listPath);
// sw.Write(args.Request.ContentString);
// }
// catch (Exception e)
// {
// string err = string.Format("Error writing received presets file:\r{0}", e);
// CrestronConsole.PrintLine(err);
// ErrorLog.Warn(err);
// // Put file back
// File.Move(listPath + ".bak", listPath);
// args.Response.Code = 500;
// return;
// }
// }
// }
// }
// void HandleApiGetPresetsLists(HttpServerRequest request, HttpServerResponse response)
// {
// if (request.Header.RequestType != "GET")
// {
// response.Code = 404; // This should be a 405 with an allow header
// return;
// }
// if (Directory.Exists(PresetsPathPrefix))
// {
// //CrestronConsole.PrintLine("Parsing presets directory");
// List<string> files = Directory.GetFiles(PresetsPathPrefix, "*.json")
// .ToList().Select(f => Path.GetFileName(f)).ToList();
// if (files.Count > 0)
// files.Sort();
// var json = JsonConvert.SerializeObject(files);
// response.Header.ContentType = "application/json";
// response.ContentString = json;
// }
// // //CrestronConsole.PrintLine("Found {0} files", files.Count);
// // JObject jo = new JObject();
// // JArray ja = new JArray();
// // foreach (var filename in files)
// // {
// // try
// // {
// // using (StreamReader sr = new StreamReader(filename))
// // {
// // JObject tempJo = JObject.Parse(sr.ReadToEnd());
// // if (tempJo.Value<string>("content").Equals("presetsList"))
// // {
// // var jItem = new JObject(); // make a new object
// // jItem.Add("Name", tempJo["name"]);
// // jItem.Add("File", filename);
// // jItem.Add("Url", Uri.EscapeUriString(new Uri(
// // filename.Replace("\\html", "")
// // .Replace("\\HTML", "")
// // .Replace('\\', '/'), UriKind.Relative).ToString()));
// // ja.Add(jItem); // add to array
// // }
// // else
// // CrestronConsole.PrintLine("Cannot use presets file '{0}'", filename);
// // }
// // }
// // catch
// // {
// // // ignore failures - maybe delete them
// // CrestronConsole.PrintLine("Unable to read presets file '{0}'", filename);
// // }
// // }
// // jo.Add("PresetChannelLists", ja);
// // //CrestronConsole.PrintLine(jo.ToString());
// // response.Header.ContentType = "application/json";
// // response.ContentString = jo.ToString();
// //}
// //else
// // CrestronConsole.PrintLine("No presets files in directory");
// }
// /// <summary>
// /// Simply does what it says
// /// </summary>
// JObject GetContentStringJson(OnHttpRequestArgs args)
// {
// //var content = args.Request.ContentString;
// //Debug.Console(1, "{0}", content);
// try
// {
// // just see if it parses properly
// return JObject.Parse(args.Request.ContentString);
// }
// catch (Exception e)
// {
// string err = string.Format("JSON Error reading config file:\r{0}", e);
// CrestronConsole.PrintLine(err);
// ErrorLog.Warn(err);
// args.Response.Code = 400; // Bad request
// return null;
// }
// }
// }
//}

View File

@@ -166,7 +166,7 @@
<Compile Include="ControlSystem.cs" />
<Compile Include="Factory\UiDeviceFactory.cs" />
<Compile Include="Fusion\EssentialsHuddleVtc1FusionController.cs" />
<Compile Include="HttpApiHandler.cs" />
<Compile Include="PluginLoading\PluginLoading.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Room\Config\EssentialsDualDisplayRoomPropertiesConfig.cs" />
<Compile Include="Room\Config\EssentialsNDisplayRoomPropertiesConfig.cs" />

View File

@@ -0,0 +1,444 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.Reflection;
using PepperDash.Core;
using PepperDash.Essentials.Core;
namespace PepperDash.Essentials
{
/// <summary>
/// Deals with loading plugins at runtime
/// </summary>
public static class PluginLoader
{
/// <summary>
/// The complete list of loaded assemblies. Includes Essentials Framework assemblies and plugins
/// </summary>
public static List<LoadedAssembly> LoadedAssemblies { get; private set; }
/// <summary>
/// The list of assemblies loaded from the plugins folder
/// </summary>
static List<LoadedAssembly> LoadedPluginFolderAssemblies;
/// <summary>
/// The directory to look in for .cplz plugin packages
/// </summary>
static string _pluginDirectory = Global.FilePathPrefix + "plugins";
/// <summary>
/// The directory where plugins will be moved to and loaded from
/// </summary>
static string _loadedPluginsDirectoryPath = _pluginDirectory + Global.DirectorySeparator + "loadedAssemblies";
// The temp directory where .cplz archives will be unzipped to
static string _tempDirectory = _pluginDirectory + Global.DirectorySeparator + "temp";
static PluginLoader()
{
LoadedAssemblies = new List<LoadedAssembly>();
LoadedPluginFolderAssemblies = new List<LoadedAssembly>();
}
/// <summary>
/// Retrieves all the loaded assemblies from the program directory
/// </summary>
public static void AddProgramAssemblies()
{
Debug.Console(2, "Getting Assemblies loaded with Essentials");
// Get the loaded assembly filenames
var appDi = new DirectoryInfo(Global.ApplicationDirectoryPathPrefix);
var assemblyFiles = appDi.GetFiles("*.dll");
Debug.Console(2, "Found {0} Assemblies", assemblyFiles.Length);
foreach (var fi in assemblyFiles)
{
string version = string.Empty;
Assembly assembly = null;
switch (fi.Name)
{
case ("PepperDashEssentials.dll"):
{
version = Global.AssemblyVersion;
assembly = Assembly.GetExecutingAssembly();
break;
}
case ("PepperDash_Core.dll"):
{
version = PepperDash.Core.Debug.PepperDashCoreVersion;
break;
}
}
LoadedAssemblies.Add(new LoadedAssembly(fi.Name, version, assembly));
}
if (Debug.Level > 1)
{
Debug.Console(2, "Loaded Assemblies:");
foreach (var assembly in LoadedAssemblies)
{
Debug.Console(2, "Assembly: {0}", assembly.Name);
}
}
}
/// <summary>
/// Loads an assembly via Reflection and adds it to the list of loaded assemblies
/// </summary>
/// <param name="fileName"></param>
static LoadedAssembly LoadAssembly(string filePath)
{
Debug.Console(2, "Attempting to load {0}", filePath);
var assembly = Assembly.LoadFrom(filePath);
if (assembly != null)
{
var assyVersion = GetAssemblyVersion(assembly);
var loadedAssembly = new LoadedAssembly(assembly.GetName().Name, assyVersion, assembly);
LoadedAssemblies.Add(loadedAssembly);
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Loaded assembly '{0}', version {1}", loadedAssembly.Name, loadedAssembly.Version);
return loadedAssembly;
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Unable to load assembly: '{0}'", filePath);
}
return null;
}
/// <summary>
/// Attempts to get the assembly informational version and if not possible gets the version
/// </summary>
/// <param name="assembly"></param>
/// <returns></returns>
static string GetAssemblyVersion(Assembly assembly)
{
var ver = assembly.GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false);
if (ver != null && ver.Length > 0)
{
// Get the AssemblyInformationalVersion
AssemblyInformationalVersionAttribute verAttribute = ver[0] as AssemblyInformationalVersionAttribute;
return verAttribute.InformationalVersion;
}
else
{
// Get the AssemblyVersion
var version = assembly.GetName().Version;
var verStr = string.Format("{0}.{1}.{2}.{3}", version.Major, version.Minor, version.Build, version.Revision);
return verStr;
}
}
/// <summary>
/// Checks if the filename matches an already loaded assembly file's name
/// </summary>
/// <param name="filename"></param>
/// <returns>True if file already matches loaded assembly file.</returns>
public static bool CheckIfAssemblyLoaded(string name)
{
Debug.Console(2, "Checking if assembly: {0} is loaded...", name);
var loadedAssembly = LoadedAssemblies.FirstOrDefault(s => s.Name.Equals(name));
if (loadedAssembly != null)
{
Debug.Console(2, "Assembly already loaded.");
return true;
}
else
{
Debug.Console(2, "Assembly not loaded.");
return false;
}
}
/// <summary>
/// Used by console command to report the currently loaded assemblies and versions
/// </summary>
/// <param name="command"></param>
public static void ReportAssemblyVersions(string command)
{
Debug.Console(0, "Loaded Assemblies:");
foreach (var assembly in LoadedAssemblies)
{
Debug.Console(0, "{0} Version: {1}", assembly.Name, assembly.Version);
}
}
/// <summary>
/// Moves any .dll assemblies not already loaded from the plugins folder to loadedPlugins folder
/// </summary>
static void MoveDllAssemblies()
{
Debug.Console(0, "Looking for .dll assemblies from plugins folder...");
var pluginDi = new DirectoryInfo(_pluginDirectory);
var pluginFiles = pluginDi.GetFiles("*.dll");
if (pluginFiles.Length > 0)
{
if (!Directory.Exists(_loadedPluginsDirectoryPath))
{
Directory.CreateDirectory(_loadedPluginsDirectoryPath);
}
}
foreach (var pluginFile in pluginFiles)
{
try
{
Debug.Console(0, "Found .dll: {0}", pluginFile.Name);
if (!CheckIfAssemblyLoaded(pluginFile.Name))
{
string filePath = string.Empty;
filePath = _loadedPluginsDirectoryPath + Global.DirectorySeparator + pluginFile.Name;
// Check if there is a previous file in the loadedPlugins directory and delete
if (File.Exists(filePath))
{
Debug.Console(0, "Found existing file in loadedPlugins: {0} Deleting and moving new file to replace it", filePath);
File.Delete(filePath);
}
// Move the file
File.Move(pluginFile.FullName, filePath);
Debug.Console(2, "Moved {0} to {1}", pluginFile.FullName, filePath);
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Skipping assembly: {0}. There is already an assembly with that name loaded.", pluginFile.FullName);
}
}
catch (Exception e)
{
Debug.Console(2, "Error with plugin file {0} . Exception: {1}", pluginFile.FullName, e);
continue; //catching any load issues and continuing. There will be exceptions loading Crestron .dlls from the cplz Probably should do something different here
}
}
Debug.Console(0, "Done with .dll assemblies");
}
/// <summary>
/// Unzips each .cplz archive into the temp directory and moves any unloaded files into loadedPlugins
/// </summary>
static void UnzipAndMoveCplzArchives()
{
Debug.Console(0, "Looking for .cplz archives from plugins folder...");
var di = new DirectoryInfo(_pluginDirectory);
var zFiles = di.GetFiles("*.cplz");
if (zFiles.Length > 0)
{
if (!Directory.Exists(_loadedPluginsDirectoryPath))
{
Directory.CreateDirectory(_loadedPluginsDirectoryPath);
}
}
foreach (var zfi in zFiles)
{
Directory.CreateDirectory(_tempDirectory);
var tempDi = new DirectoryInfo(_tempDirectory);
Debug.Console(0, "Found cplz: {0}. Unzipping into temp plugins directory", zfi.Name);
var result = CrestronZIP.Unzip(zfi.FullName, tempDi.FullName);
Debug.Console(0, "UnZip Result: {0}", result.ToString());
var tempFiles = tempDi.GetFiles("*.dll");
foreach (var tempFile in tempFiles)
{
try
{
if (!CheckIfAssemblyLoaded(tempFile.Name))
{
string filePath = string.Empty;
filePath = _loadedPluginsDirectoryPath + Global.DirectorySeparator + tempFile.Name;
// Check if there is a previous file in the loadedPlugins directory and delete
if (File.Exists(filePath))
{
Debug.Console(0, "Found existing file in loadedPlugins: {0} Deleting and moving new file to replace it", filePath);
File.Delete(filePath);
}
// Move the file
File.Move(tempFile.FullName, filePath);
Debug.Console(2, "Moved {0} to {1}", tempFile.FullName, filePath);
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Skipping assembly: {0}. There is already an assembly with that name loaded.", tempFile.FullName);
}
}
catch (Exception e)
{
Debug.Console(2, "Assembly {0} is not a custom assembly. Exception: {1}", tempFile.FullName, e);
continue; //catching any load issues and continuing. There will be exceptions loading Crestron .dlls from the cplz Probably should do something different here
}
}
// Delete the .cplz and the temp directory
Directory.Delete(_tempDirectory, true);
zfi.Delete();
}
Debug.Console(0, "Done with .cplz archives");
}
/// <summary>
/// Attempts to load the assemblies from the loadedPlugins folder
/// </summary>
static void LoadPluginAssemblies()
{
Debug.Console(0, "Loading assemblies from loadedPlugins folder...");
var pluginDi = new DirectoryInfo(_loadedPluginsDirectoryPath);
var pluginFiles = pluginDi.GetFiles("*.dll");
Debug.Console(2, "Found {0} plugin assemblies to load", pluginFiles.Length);
foreach (var pluginFile in pluginFiles)
{
var loadedAssembly = LoadAssembly(pluginFile.FullName);
LoadedPluginFolderAssemblies.Add(loadedAssembly);
}
Debug.Console(0, "All Plugins Loaded.");
}
/// <summary>
/// Iterate the loaded assemblies and try to call the LoadPlugin method
/// </summary>
static void LoadCustomPluginTypes()
{
Debug.Console(0, "Loading Custom Plugin Types...");
foreach (var loadedAssembly in LoadedPluginFolderAssemblies)
{
// iteratate this assembly's classes, looking for "LoadPlugin()" methods
try
{
var assy = loadedAssembly.Assembly;
var types = assy.GetTypes();
foreach (var type in types)
{
try
{
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
var loadPlugin = methods.FirstOrDefault(m => m.Name.Equals("LoadPlugin"));
if (loadPlugin != null)
{
Debug.Console(2, "LoadPlugin method found in {0}", type.Name);
var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static);
var minimumVersion = fields.FirstOrDefault(p => p.Name.Equals("MinimumEssentialsFrameworkVersion"));
if (minimumVersion != null)
{
Debug.Console(2, "MinimumEssentialsFrameworkVersion found");
var minimumVersionString = minimumVersion.GetValue(null) as string;
if (!string.IsNullOrEmpty(minimumVersionString))
{
var passed = Global.IsRunningMinimumVersionOrHigher(minimumVersionString);
if (!passed)
{
Debug.Console(0, Debug.ErrorLogLevel.Error, "Plugin indicates minimum Essentials version {0}. Dependency check failed. Skipping Plugin", minimumVersionString);
continue;
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Passed plugin passed dependency check (required version {0})", minimumVersionString);
}
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Warning, "MinimumEssentialsFrameworkVersion found but not set. Loading plugin, but your mileage may vary.");
}
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Warning, "MinimumEssentialsFrameworkVersion not found. Loading plugin, but your mileage may vary.");
}
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Adding plugin: {0}", loadedAssembly.Name);
loadPlugin.Invoke(null, null);
}
}
catch (Exception e)
{
Debug.Console(2, "Load Plugin not found. {0} is not a plugin assembly. Exception: {1}", loadedAssembly.Name, e);
continue;
}
}
}
catch (Exception e)
{
Debug.Console(2, "Error Loading Assembly: {0} Exception: (1) ", loadedAssembly.Name, e);
continue;
}
}
// plugin dll will be loaded. Any classes in plugin should have a static constructor
// that registers that class with the Core.DeviceFactory
Debug.Console(0, "Done Loading Custom Plugin Types.");
}
/// <summary>
/// Loads plugins
/// </summary>
public static void LoadPlugins()
{
if (Directory.Exists(_pluginDirectory))
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Plugins directory found, checking for plugins");
// Deal with any .dll files
MoveDllAssemblies();
// Deal with any .cplz files
UnzipAndMoveCplzArchives();
// Load the assemblies from the loadedPlugins folder into the AppDomain
LoadPluginAssemblies();
// Load the types from any custom plugin assemblies
LoadCustomPluginTypes();
}
}
}
/// <summary>
/// Represents an assembly loaded at runtime and it's associated metadata
/// </summary>
public class LoadedAssembly
{
public string Name { get; private set; }
public string Version { get; private set; }
public Assembly Assembly { get; private set; }
public LoadedAssembly(string name, string version, Assembly assembly)
{
Name = name;
Version = version;
Assembly = assembly;
}
}
}

View File

@@ -64,16 +64,23 @@ namespace PepperDash.Essentials.Core.Config
if (configFiles != null)
{
Debug.Console(2, "{0} config files found matching pattern", configFiles.Length);
if (configFiles.Length > 1)
{
Debug.Console(0, Debug.ErrorLogLevel.Error,
"****Error: Multiple Portal Configuration files present. Please ensure only a single file exists and reset program.****");
return false;
}
else
else if (configFiles.Length == 1)
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "Found Portal config file: '{0}'", filePath);
}
else
{
Debug.Console(0, Debug.ErrorLogLevel.Notice, "No config file found.");
return false;
}
}
else
{

View File

@@ -34,18 +34,34 @@ namespace PepperDash.Essentials.Core
List<Crestron.SimplSharpPro.DeviceSupport.Feedback> LinkedCrestronFeedbacks = new List<Crestron.SimplSharpPro.DeviceSupport.Feedback>();
/// <summary>
/// Creates the feedback with the Func as described.
/// </summary>
/// <remarks>
/// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge,
/// it will NOT reflect an actual value from a device until <seealso cref="FireUpdate"/> has been called
/// </remarks>
/// <param name="valueFunc">Delegate to invoke when this feedback needs to be updated</param>
public BoolFeedback(Func<bool> valueFunc)
: this(null, valueFunc)
{
}
/// <summary>
/// Creates the feedback with the Func as described.
/// </summary>
/// <remarks>
/// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge,
/// it will NOT reflect an actual value from a device until <seealso cref="FireUpdate"/> has been called
/// </remarks>
/// <param name="key">Key to find this Feedback</param>
/// <param name="valueFunc">Delegate to invoke when this feedback needs to be updated</param>
public BoolFeedback(string key, Func<bool> valueFunc)
: base(key)
{
ValueFunc = valueFunc;
}
public override void FireUpdate()
{
bool newValue = InTestMode ? TestValue : ValueFunc.Invoke();

View File

@@ -23,11 +23,28 @@ namespace PepperDash.Essentials.Core
Func<int> ValueFunc;
List<UShortInputSig> LinkedInputSigs = new List<UShortInputSig>();
/// <summary>
/// Creates the feedback with the Func as described.
/// </summary>
/// <remarks>
/// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge,
/// it will NOT reflect an actual value from a device until <seealso cref="FireUpdate"/> has been called
/// </remarks>
/// <param name="valueFunc">Delegate to invoke when this feedback needs to be updated</param>
public IntFeedback(Func<int> valueFunc)
: this(null, valueFunc)
{
}
/// <summary>
/// Creates the feedback with the Func as described.
/// </summary>
/// <remarks>
/// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge,
/// it will NOT reflect an actual value from a device until <seealso cref="FireUpdate"/> has been called
/// </remarks>
/// <param name="key">Key to find this Feedback</param>
/// <param name="valueFunc">Delegate to invoke when this feedback needs to be updated</param>
public IntFeedback(string key, Func<int> valueFunc)
: base(key)
{

View File

@@ -7,6 +7,7 @@ using Crestron.SimplSharpPro;
namespace PepperDash.Essentials.Core
{
public class StringFeedback : Feedback
{
public override string StringValue { get { return _StringValue; } } // ValueFunc.Invoke(); } }
@@ -18,16 +19,33 @@ namespace PepperDash.Essentials.Core
public string TestValue { get; private set; }
/// <summary>
/// Evalutated on FireUpdate
/// Evaluated on FireUpdate
/// </summary>
public Func<string> ValueFunc { get; private set; }
List<StringInputSig> LinkedInputSigs = new List<StringInputSig>();
/// <summary>
/// Creates the feedback with the Func as described.
/// </summary>
/// <remarks>
/// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge,
/// it will NOT reflect an actual value from a device until <seealso cref="FireUpdate"/> has been called
/// </remarks>
/// <param name="valueFunc">Delegate to invoke when this feedback needs to be updated</param>
public StringFeedback(Func<string> valueFunc)
: this(null, valueFunc)
{
}
/// <summary>
/// Creates the feedback with the Func as described.
/// </summary>
/// <remarks>
/// While the linked sig value will be updated with the current value stored when it is linked to a EISC Bridge,
/// it will NOT reflect an actual value from a device until <seealso cref="FireUpdate"/> has been called
/// </remarks>
/// <param name="key">Key to find this Feedback</param>
/// <param name="valueFunc">Delegate to invoke when this feedback needs to be updated</param>
public StringFeedback(string key, Func<string> valueFunc)
: base(key)
{

View File

@@ -98,7 +98,7 @@ namespace PepperDash.Essentials.Core
{
Debug.Console(2, "Comparing running version '{0}' to minimum version '{1}'", AssemblyVersion, minimumVersion);
var runtimeVersion = Regex.Match(AssemblyVersion, @"^(\d*).(\d*).(\d*)$");
var runtimeVersion = Regex.Match(AssemblyVersion, @"^(\d*).(\d*).(\d*).*");
var runtimeVersionMajor = Int16.Parse(runtimeVersion.Groups[1].Value);
var runtimeVersionMinor = Int16.Parse(runtimeVersion.Groups[2].Value);
@@ -107,7 +107,7 @@ namespace PepperDash.Essentials.Core
// Check for beta build version
if (runtimeVersionMajor == 0)
{
Debug.Console(2, "Running Beta Build. Bypassing Dependency Check.");
Debug.Console(2, "Running Local Build. Bypassing Dependency Check.");
return true;
}

View File

@@ -1,13 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro.Diagnostics;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
@@ -19,18 +14,32 @@ namespace PepperDash.Essentials.Core.Monitoring
/// </summary>
public class SystemMonitorController : Device
{
private const long UptimePollTime = 300000;
private CTimer _uptimePollTimer;
private string _uptime;
private string _lastStart;
public event EventHandler<EventArgs> SystemMonitorPropertiesChanged;
public Dictionary<uint, ProgramStatusFeedbacks> ProgramStatusFeedbackCollection;
public Dictionary<short, EthernetStatusFeedbacks> EthernetStatusFeedbackCollection;
public IntFeedback TimeZoneFeedback { get; set; }
public StringFeedback TimeZoneTextFeedback { get; set; }
public IntFeedback TimeZoneFeedback { get; protected set; }
public StringFeedback TimeZoneTextFeedback { get; protected set; }
public StringFeedback IoControllerVersionFeedback { get; protected set; }
public StringFeedback SnmpVersionFeedback { get; protected set; }
public StringFeedback BaCnetAppVersionFeedback { get; protected set; }
public StringFeedback ControllerVersionFeedback { get; protected set; }
//new feedbacks. Issue #50
public StringFeedback SerialNumberFeedback { get; protected set; }
public StringFeedback ModelFeedback { get; set; }
public StringFeedback UptimeFeedback { get; set; }
public StringFeedback LastStartFeedback { get; set; }
public StringFeedback IOControllerVersionFeedback { get; set; }
public StringFeedback SnmpVersionFeedback { get; set; }
public StringFeedback BACnetAppVersionFeedback { get; set; }
public StringFeedback ControllerVersionFeedback { get; set; }
public SystemMonitorController(string key)
: base(key)
{
@@ -38,21 +47,18 @@ namespace PepperDash.Essentials.Core.Monitoring
SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true;
//CrestronConsole.AddNewConsoleCommand(RefreshSystemMonitorData, "RefreshSystemMonitor", "Refreshes System Monitor Feedbacks", ConsoleAccessLevelEnum.AccessOperator);
TimeZoneFeedback = new IntFeedback(() => SystemMonitor.TimeZoneInformation.TimeZoneNumber);
TimeZoneTextFeedback = new StringFeedback(() => SystemMonitor.TimeZoneInformation.TimeZoneName);
TimeZoneFeedback = new IntFeedback(new Func<int>( () => SystemMonitor.TimeZoneInformation.TimeZoneNumber));
TimeZoneTextFeedback = new StringFeedback(new Func<string>( () => SystemMonitor.TimeZoneInformation.TimeZoneName));
IoControllerVersionFeedback = new StringFeedback(() => SystemMonitor.VersionInformation.IOPVersion);
SnmpVersionFeedback = new StringFeedback(() => SystemMonitor.VersionInformation.SNMPVersion);
BaCnetAppVersionFeedback = new StringFeedback(() => SystemMonitor.VersionInformation.BACNetVersion);
ControllerVersionFeedback = new StringFeedback(() => SystemMonitor.VersionInformation.ControlSystemVersion);
IOControllerVersionFeedback = new StringFeedback(new Func<string>( () => SystemMonitor.VersionInformation.IOPVersion));
SnmpVersionFeedback = new StringFeedback(new Func<string>( () => SystemMonitor.VersionInformation.SNMPVersion));
BACnetAppVersionFeedback = new StringFeedback(new Func<string>( () => SystemMonitor.VersionInformation.BACNetVersion));
ControllerVersionFeedback = new StringFeedback(new Func<string>( () => SystemMonitor.VersionInformation.ControlSystemVersion));
//var status = string.Format("System Monitor Status: \r TimeZone: {0}\rTimeZoneText: {1}\rIOControllerVersion: {2}\rSnmpAppVersionFeedback: {3}\rBACnetAppVersionFeedback: {4}\rControllerVersionFeedback: {5}",
// SystemMonitor.TimeZoneInformation.TimeZoneNumber, SystemMonitor.TimeZoneInformation.TimeZoneName, SystemMonitor.VersionInformation.IOPVersion, SystemMonitor.VersionInformation.SNMPVersion,
// SystemMonitor.VersionInformation.BACNetVersion, SystemMonitor.VersionInformation.ControlSystemVersion);
//Debug.Console(1, this, status);
SerialNumberFeedback = new StringFeedback(() => CrestronEnvironment.SystemInfo.SerialNumber);
ModelFeedback = new StringFeedback(() => InitialParametersClass.ControllerPromptName);
UptimeFeedback = new StringFeedback(() => _uptime);
LastStartFeedback = new StringFeedback(()=> _lastStart);
ProgramStatusFeedbackCollection = new Dictionary<uint, ProgramStatusFeedbacks>();
@@ -62,43 +68,132 @@ namespace PepperDash.Essentials.Core.Monitoring
ProgramStatusFeedbackCollection.Add(prog.Number, program);
}
SystemMonitor.ProgramChange += new ProgramStateChangeEventHandler(SystemMonitor_ProgramChange);
SystemMonitor.TimeZoneInformation.TimeZoneChange += new TimeZoneChangeEventHandler(TimeZoneInformation_TimeZoneChange);
CreateEthernetStatusFeedbacks();
UpdateEthernetStatusFeeedbacks();
_uptimePollTimer = new CTimer(PollUptime,null,0, UptimePollTime);
SystemMonitor.ProgramChange += SystemMonitor_ProgramChange;
SystemMonitor.TimeZoneInformation.TimeZoneChange += TimeZoneInformation_TimeZoneChange;
CrestronEnvironment.EthernetEventHandler += CrestronEnvironmentOnEthernetEventHandler;
CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironmentOnProgramStatusEventHandler;
}
private void CrestronEnvironmentOnProgramStatusEventHandler(eProgramStatusEventType programEventType)
{
if (programEventType != eProgramStatusEventType.Stopping) return;
_uptimePollTimer.Stop();
_uptimePollTimer.Dispose();
_uptimePollTimer = null;
}
private void PollUptime(object obj)
{
var consoleResponse = string.Empty;
CrestronConsole.SendControlSystemCommand("uptime", ref consoleResponse);
ParseUptime(consoleResponse);
UptimeFeedback.FireUpdate();
LastStartFeedback.FireUpdate();
}
private void ParseUptime(string response)
{
var splitString = response.Trim().Split('\r', '\n');
var lastStartRaw = splitString[2];
var lastStartIndex = lastStartRaw.IndexOf(':');
_lastStart = lastStartRaw.Substring(lastStartIndex + 1).Trim();
var uptimeRaw = splitString[0];
var forIndex = uptimeRaw.IndexOf("for", StringComparison.Ordinal);
//4 => "for " to get what's on the right
_uptime = uptimeRaw.Substring(forIndex + 4);
}
private void CrestronEnvironmentOnEthernetEventHandler(EthernetEventArgs ethernetEventArgs)
{
if (ethernetEventArgs.EthernetEventType != eEthernetEventType.LinkUp) return;
foreach (var fb in EthernetStatusFeedbackCollection)
{
fb.Value.UpdateEthernetStatus();
}
}
private void CreateEthernetStatusFeedbacks()
{
EthernetStatusFeedbackCollection = new Dictionary<short, EthernetStatusFeedbacks>();
Debug.Console(2, "Creating {0} EthernetStatusFeedbacks", InitialParametersClass.NumberOfEthernetInterfaces);
for (short i = 0; i < InitialParametersClass.NumberOfEthernetInterfaces; i++)
{
Debug.Console(2, "Creating EthernetStatusFeedback for Interface {0}", i);
var ethernetInterface = new EthernetStatusFeedbacks(i);
EthernetStatusFeedbackCollection.Add(i, ethernetInterface);
}
}
private void UpdateEthernetStatusFeeedbacks()
{
foreach (var iface in EthernetStatusFeedbackCollection)
{
iface.Value.CurrentIpAddressFeedback.FireUpdate();
iface.Value.CurrentSubnetMaskFeedback.FireUpdate();
iface.Value.CurrentDefaultGatewayFeedback.FireUpdate();
iface.Value.StaticIpAddressFeedback.FireUpdate();
iface.Value.StaticSubnetMaskFeedback.FireUpdate();
iface.Value.StaticDefaultGatewayFeedback.FireUpdate();
iface.Value.HostNameFeedback.FireUpdate();
iface.Value.DnsServerFeedback.FireUpdate();
iface.Value.DomainFeedback.FireUpdate();
iface.Value.DhcpStatusFeedback.FireUpdate();
iface.Value.MacAddressFeedback.FireUpdate();
}
}
/// <summary>
/// Gets data in separate thread
/// </summary>
/// <param name="command"></param>
void RefreshSystemMonitorData(string command)
private void RefreshSystemMonitorData()
{
// this takes a while, launch a new thread
CrestronInvoke.BeginInvoke((o) =>
{
TimeZoneFeedback.FireUpdate();
TimeZoneTextFeedback.FireUpdate();
IOControllerVersionFeedback.FireUpdate();
SnmpVersionFeedback.FireUpdate();
BACnetAppVersionFeedback.FireUpdate();
ControllerVersionFeedback.FireUpdate();
OnSystemMonitorPropertiesChanged();
}
);
CrestronInvoke.BeginInvoke(UpdateFeedback);
}
void OnSystemMonitorPropertiesChanged()
private void UpdateFeedback(object o)
{
TimeZoneFeedback.FireUpdate();
TimeZoneTextFeedback.FireUpdate();
IoControllerVersionFeedback.FireUpdate();
SnmpVersionFeedback.FireUpdate();
BaCnetAppVersionFeedback.FireUpdate();
ControllerVersionFeedback.FireUpdate();
SerialNumberFeedback.FireUpdate();
ModelFeedback.FireUpdate();
OnSystemMonitorPropertiesChanged();
}
private void OnSystemMonitorPropertiesChanged()
{
var handler = SystemMonitorPropertiesChanged;
if (handler != null)
{
handler(this, new EventArgs());
handler(this, new EventArgs());
}
}
public override bool CustomActivate()
{
RefreshSystemMonitorData(null);
RefreshSystemMonitorData();
return base.CustomActivate();
}
@@ -114,46 +209,41 @@ namespace PepperDash.Essentials.Core.Monitoring
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
void SystemMonitor_ProgramChange(Program sender, ProgramEventArgs args)
private void SystemMonitor_ProgramChange(Program sender, ProgramEventArgs args)
{
Debug.Console(2, this, "Program Change Detected for slot: {0}", sender.Number);
Debug.Console(2, this, "Event Type: {0}", args.EventType);
var program = ProgramStatusFeedbackCollection[sender.Number];
if (args.EventType == eProgramChangeEventType.OperatingState)
switch (args.EventType)
{
program.ProgramStartedFeedback.FireUpdate();
program.ProgramStoppedFeedback.FireUpdate();
program.ProgramInfo.OperatingState = args.OperatingState;
//program.GetProgramInfo();
if (args.OperatingState == eProgramOperatingState.Start)
program.GetProgramInfo();
else
{
program.AggregatedProgramInfoFeedback.FireUpdate();
program.OnProgramInfoChanged();
}
case eProgramChangeEventType.OperatingState:
program.ProgramStartedFeedback.FireUpdate();
program.ProgramStoppedFeedback.FireUpdate();
program.ProgramInfo.OperatingState = args.OperatingState;
if (args.OperatingState == eProgramOperatingState.Start)
program.GetProgramInfo();
else
{
program.AggregatedProgramInfoFeedback.FireUpdate();
program.OnProgramInfoChanged();
}
break;
case eProgramChangeEventType.RegistrationState:
program.ProgramRegisteredFeedback.FireUpdate();
program.ProgramUnregisteredFeedback.FireUpdate();
program.ProgramInfo.RegistrationState = args.RegistrationState;
program.GetProgramInfo();
break;
}
else if (args.EventType == eProgramChangeEventType.RegistrationState)
{
program.ProgramRegisteredFeedback.FireUpdate();
program.ProgramUnregisteredFeedback.FireUpdate();
program.ProgramInfo.RegistrationState = args.RegistrationState;
program.GetProgramInfo();
}
}
/// <summary>
/// Responds to time zone changes and updates the appropriate feedbacks
/// </summary>
/// <param name="args"></param>
void TimeZoneInformation_TimeZoneChange(TimeZoneEventArgs args)
private void TimeZoneInformation_TimeZoneChange(TimeZoneEventArgs args)
{
Debug.Console(2, this, "Time Zone Change Detected.");
TimeZoneFeedback.FireUpdate();
@@ -162,6 +252,121 @@ namespace PepperDash.Essentials.Core.Monitoring
OnSystemMonitorPropertiesChanged();
}
public class EthernetStatusFeedbacks
{
public StringFeedback HostNameFeedback { get; protected set; }
public StringFeedback DnsServerFeedback { get; protected set; }
public StringFeedback DomainFeedback { get; protected set; }
public StringFeedback MacAddressFeedback { get; protected set; }
public StringFeedback DhcpStatusFeedback { get; protected set; }
public StringFeedback CurrentIpAddressFeedback { get; protected set; }
public StringFeedback CurrentSubnetMaskFeedback { get; protected set; }
public StringFeedback CurrentDefaultGatewayFeedback { get; protected set; }
public StringFeedback StaticIpAddressFeedback { get; protected set; }
public StringFeedback StaticSubnetMaskFeedback { get; protected set; }
public StringFeedback StaticDefaultGatewayFeedback { get; protected set; }
public EthernetStatusFeedbacks(short adapterIndex)
{
Debug.Console(2, "Ethernet Information for interface {0}", adapterIndex);
Debug.Console(2, "Adapter Index: {1} Hostname: {0}", CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, adapterIndex), adapterIndex);
Debug.Console(2, "Adapter Index: {1} Current IP Address: {0}", CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, adapterIndex), adapterIndex);
Debug.Console(2, "Adapter Index: {1} Current Subnet Mask: {0}", CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, adapterIndex), adapterIndex);
Debug.Console(2, "Adapter Index: {1} Current Router: {0}", CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, adapterIndex), adapterIndex);
Debug.Console(2, "Adapter Index: {1} Static IP Address: {0}", CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_STATIC_IPADDRESS, adapterIndex), adapterIndex);
Debug.Console(2, "Adapter Index: {1} Static Subnet Mask: {0}", CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_STATIC_IPMASK, adapterIndex), adapterIndex);
Debug.Console(2, "Adapter Index: {1} Static Router: {0}", CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_STATIC_ROUTER, adapterIndex), adapterIndex);
Debug.Console(2, "Adapter Index: {1} DNS Servers: {0}", CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, adapterIndex), adapterIndex);
Debug.Console(2, "Adapter Index: {1} DHCP State: {0}", CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_DHCP_STATE, adapterIndex), adapterIndex);
Debug.Console(2, "Adapter Index: {1} Domain Name: {0}", CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, adapterIndex), adapterIndex);
Debug.Console(2, "Adapter Index: {1} MAC Address: {0}", CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, adapterIndex), adapterIndex);
HostNameFeedback =
new StringFeedback(
() =>
CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, adapterIndex));
CurrentIpAddressFeedback =
new StringFeedback(
() =>
CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, adapterIndex));
CurrentDefaultGatewayFeedback =
new StringFeedback(
() =>
CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, adapterIndex));
CurrentSubnetMaskFeedback =
new StringFeedback(
() =>
CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, adapterIndex));
StaticIpAddressFeedback =
new StringFeedback(
() =>
CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, adapterIndex));
StaticDefaultGatewayFeedback =
new StringFeedback(
() =>
CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, adapterIndex));
StaticSubnetMaskFeedback =
new StringFeedback(
() =>
CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, adapterIndex));
DomainFeedback =
new StringFeedback(
() =>
CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, adapterIndex));
DnsServerFeedback =
new StringFeedback(
() =>
CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, adapterIndex));
MacAddressFeedback =
new StringFeedback(
() =>
CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, adapterIndex));
DhcpStatusFeedback = new StringFeedback(
() =>
CrestronEthernetHelper.GetEthernetParameter(
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_DHCP_STATE, adapterIndex));
}
public void UpdateEthernetStatus()
{
HostNameFeedback.FireUpdate();
CurrentIpAddressFeedback.FireUpdate();
CurrentSubnetMaskFeedback.FireUpdate();
CurrentDefaultGatewayFeedback.FireUpdate();
StaticIpAddressFeedback.FireUpdate();
StaticSubnetMaskFeedback.FireUpdate();
StaticDefaultGatewayFeedback.FireUpdate();
DomainFeedback.FireUpdate();
DnsServerFeedback.FireUpdate();
MacAddressFeedback.FireUpdate();
DhcpStatusFeedback.FireUpdate();
}
}
public class ProgramStatusFeedbacks
{
@@ -192,17 +397,19 @@ namespace PepperDash.Essentials.Core.Monitoring
ProgramInfo.OperatingState = Program.OperatingState;
ProgramInfo.RegistrationState = Program.RegistrationState;
ProgramStartedFeedback = new BoolFeedback(new Func<bool>( () => Program.OperatingState == eProgramOperatingState.Start));
ProgramStoppedFeedback = new BoolFeedback(new Func<bool>( () => Program.OperatingState == eProgramOperatingState.Stop));
ProgramRegisteredFeedback = new BoolFeedback(new Func<bool>( () => Program.RegistrationState == eProgramRegistrationState.Register));
ProgramUnregisteredFeedback = new BoolFeedback(new Func<bool>( () => Program.RegistrationState == eProgramRegistrationState.Unregister));
ProgramStartedFeedback = new BoolFeedback(() => Program.OperatingState == eProgramOperatingState.Start);
ProgramStoppedFeedback = new BoolFeedback(() => Program.OperatingState == eProgramOperatingState.Stop);
ProgramRegisteredFeedback =
new BoolFeedback(() => Program.RegistrationState == eProgramRegistrationState.Register);
ProgramUnregisteredFeedback =
new BoolFeedback(() => Program.RegistrationState == eProgramRegistrationState.Unregister);
ProgramNameFeedback = new StringFeedback(new Func<string>(() => ProgramInfo.ProgramFile));
ProgramCompileTimeFeedback = new StringFeedback(new Func<string>(() => ProgramInfo.CompileTime));
CrestronDataBaseVersionFeedback = new StringFeedback(new Func<string>(() => ProgramInfo.CrestronDB));
EnvironmentVersionFeedback = new StringFeedback(new Func<string>(() => ProgramInfo.Environment));
ProgramNameFeedback = new StringFeedback(() => ProgramInfo.ProgramFile);
ProgramCompileTimeFeedback = new StringFeedback(() => ProgramInfo.CompileTime);
CrestronDataBaseVersionFeedback = new StringFeedback(() => ProgramInfo.CrestronDb);
EnvironmentVersionFeedback = new StringFeedback(() => ProgramInfo.Environment);
AggregatedProgramInfoFeedback = new StringFeedback(new Func<string>(() => JsonConvert.SerializeObject(ProgramInfo)));
AggregatedProgramInfoFeedback = new StringFeedback(() => JsonConvert.SerializeObject(ProgramInfo));
GetProgramInfo();
}
@@ -212,74 +419,99 @@ namespace PepperDash.Essentials.Core.Monitoring
/// </summary>
public void GetProgramInfo()
{
CrestronInvoke.BeginInvoke((o) =>
CrestronInvoke.BeginInvoke(GetProgramInfo);
}
private void GetProgramInfo(object o)
{
Debug.Console(2, "Attempting to get program info for slot: {0}", Program.Number);
string response = null;
if (Program.RegistrationState == eProgramRegistrationState.Unregister || Program.OperatingState == eProgramOperatingState.Stop)
{
Debug.Console(2, "Attempting to get program info for slot: {0}", Program.Number);
Debug.Console(2, "Program {0} not registered. Setting default values for program information.",
Program.Number);
string response = null;
var success = CrestronConsole.SendControlSystemCommand(string.Format("progcomments:{0}", Program.Number), ref response);
if (success)
ProgramInfo = new ProgramInfo(Program.Number)
{
//Debug.Console(2, "Progcomments Response: \r{0}", response);
OperatingState = Program.OperatingState,
RegistrationState = Program.RegistrationState
};
if (!response.ToLower().Contains("bad or incomplete"))
{
// Shared properteis
ProgramInfo.ProgramFile = ParseConsoleData(response, "Program File", ": ", "\n");
ProgramInfo.CompilerRevision = ParseConsoleData(response, "Compiler Rev", ": ", "\n");
ProgramInfo.CompileTime = ParseConsoleData(response, "Compiled On", ": ", "\n");
ProgramInfo.Include4Dat = ParseConsoleData(response, "Include4.dat", ": ", "\n");
return;
}
var success = CrestronConsole.SendControlSystemCommand(
string.Format("progcomments:{0}", Program.Number), ref response);
if (!success)
{
Debug.Console(2, "Progcomments Attempt Unsuccessful for slot: {0}", Program.Number);
UpdateFeedbacks();
return;
}
if (ProgramInfo.ProgramFile.Contains(".dll"))
{
// SSP Program
ProgramInfo.FriendlyName = ParseConsoleData(response, "Friendly Name", ": ", "\n");
ProgramInfo.ApplicationName = ParseConsoleData(response, "Application Name", ": ", "\n");
ProgramInfo.ProgramTool = ParseConsoleData(response, "Program Tool", ": ", "\n");
ProgramInfo.MinFirmwareVersion = ParseConsoleData(response, "Min Firmware Version", ": ", "\n");
ProgramInfo.PlugInVersion = ParseConsoleData(response, "PlugInVersion", ": ", "\n");
}
else if (ProgramInfo.ProgramFile.Contains(".smw"))
{
// SIMPL Windows Program
ProgramInfo.FriendlyName = ParseConsoleData(response, "Friendly Name", ":", "\n");
ProgramInfo.SystemName = ParseConsoleData(response, "System Name", ": ", "\n");
ProgramInfo.CrestronDB = ParseConsoleData(response, "CrestronDB", ": ", "\n");
ProgramInfo.Environment = ParseConsoleData(response, "Source Env", ": ", "\n");
ProgramInfo.Programmer = ParseConsoleData(response, "Programmer", ": ", "\n");
if (response.ToLower().Contains("bad or incomplete"))
{
Debug.Console(2,
"Program in slot {0} not running. Setting default ProgramInfo for slot: {0}",
Program.Number);
}
//Debug.Console(2, "ProgramInfo: \r{0}", JsonConvert.SerializeObject(ProgramInfo));
}
else
{
Debug.Console(2, "Bad or incomplete console command response. Initializing ProgramInfo for slot: {0}", Program.Number);
// Assume no valid program info. Constructing a new object will wipe all properties
ProgramInfo = new ProgramInfo(Program.Number);
ProgramInfo.OperatingState = Program.OperatingState;
ProgramInfo.RegistrationState = Program.RegistrationState;
}
}
else
// Assume no valid program info. Constructing a new object will wipe all properties
ProgramInfo = new ProgramInfo(Program.Number)
{
Debug.Console(2, "Progcomments Attempt Unsuccessful for slot: {0}", Program.Number);
}
OperatingState = Program.OperatingState,
RegistrationState = Program.RegistrationState
};
ProgramNameFeedback.FireUpdate();
ProgramCompileTimeFeedback.FireUpdate();
CrestronDataBaseVersionFeedback.FireUpdate();
EnvironmentVersionFeedback.FireUpdate();
UpdateFeedbacks();
AggregatedProgramInfoFeedback.FireUpdate();
return;
}
OnProgramInfoChanged();
});
// Shared properteis
ProgramInfo.ProgramFile = ParseConsoleData(response, "Program File", ": ", "\n");
ProgramInfo.CompilerRevision = ParseConsoleData(response, "Compiler Rev", ": ", "\n");
ProgramInfo.CompileTime = ParseConsoleData(response, "Compiled On", ": ", "\n");
ProgramInfo.Include4Dat = ParseConsoleData(response, "Include4.dat", ": ", "\n");
if (ProgramInfo.ProgramFile.Contains(".dll"))
{
// SSP Program
ProgramInfo.FriendlyName = ParseConsoleData(response, "Friendly Name", ": ", "\n");
ProgramInfo.ApplicationName = ParseConsoleData(response, "Application Name", ": ", "\n");
ProgramInfo.ProgramTool = ParseConsoleData(response, "Program Tool", ": ", "\n");
ProgramInfo.MinFirmwareVersion = ParseConsoleData(response, "Min Firmware Version", ": ",
"\n");
ProgramInfo.PlugInVersion = ParseConsoleData(response, "PlugInVersion", ": ", "\n");
}
else if (ProgramInfo.ProgramFile.Contains(".smw"))
{
// SIMPL Windows Program
ProgramInfo.FriendlyName = ParseConsoleData(response, "Friendly Name", ":", "\n");
ProgramInfo.SystemName = ParseConsoleData(response, "System Name", ": ", "\n");
ProgramInfo.CrestronDb = ParseConsoleData(response, "CrestronDB", ": ", "\n");
ProgramInfo.Environment = ParseConsoleData(response, "Source Env", ": ", "\n");
ProgramInfo.Programmer = ParseConsoleData(response, "Programmer", ": ", "\n");
}
Debug.Console(2, "Program info for slot {0} successfully updated", Program.Number);
UpdateFeedbacks();
}
private void UpdateFeedbacks()
{
ProgramNameFeedback.FireUpdate();
ProgramCompileTimeFeedback.FireUpdate();
CrestronDataBaseVersionFeedback.FireUpdate();
EnvironmentVersionFeedback.FireUpdate();
AggregatedProgramInfoFeedback.FireUpdate();
OnProgramInfoChanged();
}
public void OnProgramInfoChanged()
@@ -294,30 +526,28 @@ namespace PepperDash.Essentials.Core.Monitoring
private string ParseConsoleData(string data, string line, string startString, string endString)
{
string outputData = "";
var outputData = "";
if (data.Length > 0)
if (data.Length <= 0) return outputData;
try
{
try
{
//Debug.Console(2, "ParseConsoleData Data: {0}, Line {1}, startStirng {2}, endString {3}", data, line, startString, endString);
var linePosition = data.IndexOf(line);
var startPosition = data.IndexOf(startString, linePosition) + startString.Length;
var endPosition = data.IndexOf(endString, startPosition);
outputData = data.Substring(startPosition, endPosition - startPosition).Trim();
//Debug.Console(2, "ParseConsoleData Return: {0}", outputData);
}
catch (Exception e)
{
Debug.Console(1, "Error Parsing Console Data:\r{0}", e);
}
//Debug.Console(2, "ParseConsoleData Data: {0}, Line {1}, startStirng {2}, endString {3}", data, line, startString, endString);
var linePosition = data.IndexOf(line, StringComparison.Ordinal);
var startPosition = data.IndexOf(startString, linePosition, StringComparison.Ordinal) +
startString.Length;
var endPosition = data.IndexOf(endString, startPosition, StringComparison.Ordinal);
outputData = data.Substring(startPosition, endPosition - startPosition).Trim();
//Debug.Console(2, "ParseConsoleData Return: {0}", outputData);
}
catch (Exception e)
{
Debug.Console(1, "Error Parsing Console Data:\r{0}", e);
}
return outputData;
}
}
}
/// <summary>
@@ -330,32 +560,39 @@ namespace PepperDash.Essentials.Core.Monitoring
[JsonProperty("programNumber")]
public uint ProgramNumber { get; private set; }
[JsonConverter(typeof(StringEnumConverter))]
[JsonConverter(typeof (StringEnumConverter))]
[JsonProperty("operatingState")]
public eProgramOperatingState OperatingState { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
[JsonConverter(typeof (StringEnumConverter))]
[JsonProperty("registrationState")]
public eProgramRegistrationState RegistrationState { get; set; }
[JsonProperty("programFile")]
public string ProgramFile { get; set; }
[JsonProperty("friendlyName")]
public string FriendlyName { get; set; }
[JsonProperty("compilerRevision")]
public string CompilerRevision { get; set; }
[JsonProperty("compileTime")]
public string CompileTime { get; set; }
[JsonProperty("include4Dat")]
public string Include4Dat { get; set; }
// SIMPL Windows properties
[JsonProperty("systemName")]
public string SystemName { get; set; }
[JsonProperty("crestronDb")]
public string CrestronDB { get; set; }
public string CrestronDb { get; set; }
[JsonProperty("environment")]
public string Environment { get; set; }
[JsonProperty("programmer")]
public string Programmer { get; set; }
@@ -363,10 +600,13 @@ namespace PepperDash.Essentials.Core.Monitoring
// SSP Properties
[JsonProperty("applicationName")]
public string ApplicationName { get; set; }
[JsonProperty("programTool")]
public string ProgramTool { get; set; }
[JsonProperty("minFirmwareVersion")]
public string MinFirmwareVersion { get; set; }
[JsonProperty("plugInVersion")]
public string PlugInVersion { get; set; }
@@ -381,7 +621,7 @@ namespace PepperDash.Essentials.Core.Monitoring
Include4Dat = "";
SystemName = "";
CrestronDB = "";
CrestronDb = "";
Environment = "";
Programmer = "";

View File

@@ -84,7 +84,7 @@
</Reference>
<Reference Include="SimplSharpReflectionInterface, Version=1.0.5583.25238, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
<HintPath>..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />