mirror of
https://github.com/PepperDash/PepperDashCore.git
synced 2026-02-16 21:24:43 +00:00
Merge pull request #2 in PEC/pepperdash-simplsharp-core from bugfix/fix-ssh-20161205 to master
* commit '422947559eee5739fea933cb3dcb7b4097bcfd73': Removed handler for stream error Ssh Connect() now spins up new clients. Seems to be helping deal with connection failures Trying and failing lots of things to fix SshClient. About to try making and destroying the entire client Hunting down program crash when network cable is pulled from server. Client.ErrorOccurred is not catching this Working through elusive disconnect bugs on SSH, with Amazon on CP3N
This commit is contained in:
@@ -9,4 +9,21 @@ using Crestron.SimplSharp.CrestronSockets;
|
|||||||
namespace PepperDash.Core
|
namespace PepperDash.Core
|
||||||
{
|
{
|
||||||
public delegate void GenericSocketStatusChangeEventDelegate(ISocketStatus client);
|
public delegate void GenericSocketStatusChangeEventDelegate(ISocketStatus client);
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public class GenericSocketStatusChageEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public ISocketStatus Client { get; private set; }
|
||||||
|
|
||||||
|
public GenericSocketStatusChageEventArgs() { }
|
||||||
|
|
||||||
|
public GenericSocketStatusChageEventArgs(ISocketStatus client)
|
||||||
|
{
|
||||||
|
Client = client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -26,13 +26,12 @@ namespace PepperDash.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event when the connection status changes.
|
/// Event when the connection status changes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
//[Obsolete("Use SocketStatusChange instead")]
|
public event EventHandler<GenericSocketStatusChageEventArgs> ConnectionChange;
|
||||||
//public event EventHandler<SshConnectionChangeEventArgs> ConnectionChange;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event GenericSocketStatusChangeEventDelegate SocketStatusChange;
|
//public event GenericSocketStatusChangeEventDelegate SocketStatusChange;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Address of server
|
/// Address of server
|
||||||
@@ -63,6 +62,14 @@ namespace PepperDash.Core
|
|||||||
get { return ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
|
get { return ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// S+ helper for IsConnected
|
||||||
|
/// </summary>
|
||||||
|
public ushort UIsConnected
|
||||||
|
{
|
||||||
|
get { return (ushort)(IsConnected ? 1 : 0); }
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -93,6 +100,11 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AutoReconnect { get; set; }
|
public bool AutoReconnect { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Will be set and unset by connect and disconnect only
|
||||||
|
/// </summary>
|
||||||
|
public bool ConnectEnabled { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// S+ helper for AutoReconnect
|
/// S+ helper for AutoReconnect
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -109,13 +121,15 @@ namespace PepperDash.Core
|
|||||||
public int AutoReconnectIntervalMs { get; set; }
|
public int AutoReconnectIntervalMs { get; set; }
|
||||||
|
|
||||||
SshClient Client;
|
SshClient Client;
|
||||||
|
|
||||||
ShellStream TheStream;
|
ShellStream TheStream;
|
||||||
|
|
||||||
CTimer ReconnectTimer;
|
CTimer ReconnectTimer;
|
||||||
|
|
||||||
string PreviousHostname;
|
//string PreviousHostname;
|
||||||
int PreviousPort;
|
//int PreviousPort;
|
||||||
string PreviousUsername;
|
//string PreviousUsername;
|
||||||
string PreviousPassword;
|
//string PreviousPassword;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Typical constructor.
|
/// Typical constructor.
|
||||||
@@ -171,7 +185,8 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void Connect()
|
public void Connect()
|
||||||
{
|
{
|
||||||
Debug.Console(1, this, "attempting connect, IsConnected={0}", Client != null ? Client.IsConnected : false);
|
ConnectEnabled = true;
|
||||||
|
Debug.Console(1, this, "attempting connect");
|
||||||
|
|
||||||
// Cancel reconnect if running.
|
// Cancel reconnect if running.
|
||||||
if (ReconnectTimer != null)
|
if (ReconnectTimer != null)
|
||||||
@@ -197,55 +212,56 @@ namespace PepperDash.Core
|
|||||||
kauth.AuthenticationPrompt += new EventHandler<AuthenticationPromptEventArgs>(kauth_AuthenticationPrompt);
|
kauth.AuthenticationPrompt += new EventHandler<AuthenticationPromptEventArgs>(kauth_AuthenticationPrompt);
|
||||||
PasswordAuthenticationMethod pauth = new PasswordAuthenticationMethod(Username, Password);
|
PasswordAuthenticationMethod pauth = new PasswordAuthenticationMethod(Username, Password);
|
||||||
|
|
||||||
// always spin up new client in case parameters have changed
|
|
||||||
// **** MAY WANT TO CHANGE THIS BECAUSE OF SOCKET LEAKS ****
|
|
||||||
//if (Client != null)
|
|
||||||
//{
|
|
||||||
// Client.Disconnect();
|
|
||||||
// Client = null;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Make a new client if we need it or things have changed
|
// Make a new client if we need it or things have changed
|
||||||
if (Client == null || PropertiesHaveChanged())
|
//if (Client == null || PropertiesHaveChanged())
|
||||||
{
|
//{
|
||||||
if (Client != null)
|
if (Client != null)
|
||||||
{
|
{
|
||||||
Debug.Console(2, this, "Cleaning up disconnected client");
|
Debug.Console(2, this, "Cleaning up disconnected client");
|
||||||
Client.ErrorOccurred -= Client_ErrorOccurred;
|
Client.ErrorOccurred -= Client_ErrorOccurred;
|
||||||
if(TheStream != null)
|
KillStream();
|
||||||
TheStream.DataReceived -= Stream_DataReceived;
|
|
||||||
TheStream = null;
|
//if (TheStream != null)
|
||||||
|
//{
|
||||||
|
// TheStream.DataReceived -= Stream_DataReceived;
|
||||||
|
// TheStream.ErrorOccurred -= TheStream_ErrorOccurred;
|
||||||
|
//}
|
||||||
|
//TheStream = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.Console(2, this, "Creating new SshClient");
|
Debug.Console(2, this, "Creating new SshClient");
|
||||||
ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth);
|
ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth);
|
||||||
Client = new SshClient(connectionInfo);
|
Client = new SshClient(connectionInfo);
|
||||||
Client.ErrorOccurred += Client_ErrorOccurred;
|
Client.ErrorOccurred += Client_ErrorOccurred;
|
||||||
}
|
//}
|
||||||
PreviousHostname = Hostname;
|
//PreviousHostname = Hostname;
|
||||||
PreviousPassword = Password;
|
//PreviousPassword = Password;
|
||||||
PreviousPort = Port;
|
//PreviousPort = Port;
|
||||||
PreviousUsername = Username;
|
//PreviousUsername = Username;
|
||||||
|
|
||||||
//You can do it!
|
//You can do it!
|
||||||
ClientStatus = SocketStatus.SOCKET_STATUS_WAITING;
|
ClientStatus = SocketStatus.SOCKET_STATUS_WAITING;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Client.Connect();
|
Client.Connect();
|
||||||
if (Client.IsConnected)
|
|
||||||
{
|
// Have to assume client is connected cause Client.IsConnected is busted in some cases
|
||||||
Client.KeepAliveInterval = TimeSpan.FromSeconds(2);
|
// All other conditions *should* error out...
|
||||||
Client.SendKeepAlive();
|
//if (Client.IsConnected)
|
||||||
|
//{
|
||||||
|
//Client.KeepAliveInterval = TimeSpan.FromSeconds(2);
|
||||||
|
//Client.SendKeepAlive();
|
||||||
TheStream = Client.CreateShellStream("PDTShell", 100, 80, 100, 200, 65534);
|
TheStream = Client.CreateShellStream("PDTShell", 100, 80, 100, 200, 65534);
|
||||||
TheStream.DataReceived += Stream_DataReceived;
|
TheStream.DataReceived += Stream_DataReceived;
|
||||||
|
//TheStream.ErrorOccurred += TheStream_ErrorOccurred;
|
||||||
Debug.Console(1, this, "Connected");
|
Debug.Console(1, this, "Connected");
|
||||||
ClientStatus = SocketStatus.SOCKET_STATUS_CONNECTED;
|
ClientStatus = SocketStatus.SOCKET_STATUS_CONNECTED;
|
||||||
PreviousHostname = Hostname;
|
//PreviousHostname = Hostname;
|
||||||
PreviousPassword = Password;
|
//PreviousPassword = Password;
|
||||||
PreviousPort = Port;
|
//PreviousPort = Port;
|
||||||
PreviousUsername = Username;
|
//PreviousUsername = Username;
|
||||||
}
|
//}
|
||||||
return;
|
return; // Success will not pass here
|
||||||
}
|
}
|
||||||
catch (SshConnectionException e)
|
catch (SshConnectionException e)
|
||||||
{
|
{
|
||||||
@@ -269,54 +285,44 @@ namespace PepperDash.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sucess will not make it this far
|
// Sucess will not make it this far
|
||||||
Client.Disconnect();
|
|
||||||
ClientStatus = SocketStatus.SOCKET_STATUS_CONNECT_FAILED;
|
ClientStatus = SocketStatus.SOCKET_STATUS_CONNECT_FAILED;
|
||||||
HandleConnectionFailure();
|
HandleConnectionFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disconnect the clients and put away it's resources.
|
/// Disconnect the clients and put away it's resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Disconnect()
|
public void Disconnect()
|
||||||
{
|
{
|
||||||
|
ConnectEnabled = false;
|
||||||
// Stop trying reconnects, if we are
|
// Stop trying reconnects, if we are
|
||||||
if (ReconnectTimer != null)
|
if (ReconnectTimer != null)
|
||||||
{
|
{
|
||||||
ReconnectTimer.Stop();
|
ReconnectTimer.Stop();
|
||||||
ReconnectTimer = null;
|
ReconnectTimer = null;
|
||||||
}
|
}
|
||||||
if(TheStream != null)
|
KillStream();
|
||||||
TheStream.DataReceived -= Stream_DataReceived;
|
|
||||||
Client.Disconnect();
|
Client.Disconnect();
|
||||||
|
Client = null;
|
||||||
ClientStatus = SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY;
|
ClientStatus = SocketStatus.SOCKET_STATUS_BROKEN_LOCALLY;
|
||||||
Debug.Console(1, this, "Disconnected");
|
Debug.Console(1, this, "Disconnected");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
//void DiscoAndCleanup()
|
|
||||||
//{
|
|
||||||
// if (Client != null)
|
|
||||||
// {
|
|
||||||
// Client.ErrorOccurred -= Client_ErrorOccurred;
|
|
||||||
// TheStream.DataReceived -= Stream_DataReceived;
|
|
||||||
// Debug.Console(2, this, "Cleaning up disconnected client");
|
|
||||||
// Client.Disconnect();
|
|
||||||
// Client.Dispose();
|
|
||||||
// Client = null;
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Anything to do with reestablishing connection on failures
|
/// Anything to do with reestablishing connection on failures
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void HandleConnectionFailure()
|
void HandleConnectionFailure()
|
||||||
{
|
{
|
||||||
Debug.Console(2, this, "Checking autoreconnect: {0}, {1}ms",
|
if (Client != null)
|
||||||
AutoReconnect, AutoReconnectIntervalMs);
|
Client.Disconnect();
|
||||||
if (AutoReconnect)
|
KillStream();
|
||||||
|
|
||||||
|
if (AutoReconnect && ConnectEnabled)
|
||||||
{
|
{
|
||||||
|
Debug.Console(2, this, "Checking autoreconnect: {0}, {1}ms",
|
||||||
|
AutoReconnect, AutoReconnectIntervalMs);
|
||||||
if (ReconnectTimer == null)// || !ReconnectTimerRunning)
|
if (ReconnectTimer == null)// || !ReconnectTimerRunning)
|
||||||
{
|
{
|
||||||
ReconnectTimer = new CTimer(o =>
|
ReconnectTimer = new CTimer(o =>
|
||||||
@@ -335,12 +341,24 @@ namespace PepperDash.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PropertiesHaveChanged()
|
void KillStream()
|
||||||
{
|
{
|
||||||
return Hostname != PreviousHostname || Port != PreviousPort
|
if (TheStream != null)
|
||||||
|| Username != PreviousUsername || Password != PreviousPassword;
|
{
|
||||||
|
TheStream.DataReceived -= Stream_DataReceived;
|
||||||
|
//TheStream.ErrorOccurred -= TheStream_ErrorOccurred;
|
||||||
|
TheStream.Close();
|
||||||
|
TheStream.Dispose();
|
||||||
|
TheStream = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//bool PropertiesHaveChanged()
|
||||||
|
//{
|
||||||
|
// return Hostname != PreviousHostname || Port != PreviousPort
|
||||||
|
// || Username != PreviousUsername || Password != PreviousPassword;
|
||||||
|
//}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles the keyboard interactive authentication, should it be required.
|
/// Handles the keyboard interactive authentication, should it be required.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -371,23 +389,29 @@ namespace PepperDash.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// Handler for errors on the stream...
|
||||||
|
///// </summary>
|
||||||
|
///// <param name="sender"></param>
|
||||||
|
///// <param name="e"></param>
|
||||||
|
//void TheStream_ErrorOccurred(object sender, ExceptionEventArgs e)
|
||||||
|
//{
|
||||||
|
// Debug.Console(1, this, "Unhandled SSH STREAM error: {0}", e.Exception);
|
||||||
|
// ClientStatus = SocketStatus.SOCKET_STATUS_BROKEN_REMOTELY;
|
||||||
|
// HandleConnectionFailure();
|
||||||
|
//}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Error event handler for client events - disconnect, etc. Will forward those events via ConnectionChange
|
/// Error event handler for client events - disconnect, etc. Will forward those events via ConnectionChange
|
||||||
/// event
|
/// event
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Client_ErrorOccurred(object sender, Crestron.SimplSharp.Ssh.Common.ExceptionEventArgs e)
|
void Client_ErrorOccurred(object sender, Crestron.SimplSharp.Ssh.Common.ExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
Debug.Console(1, this, "SSH client error: {0}", e.Exception);
|
if (e.Exception is SshConnectionException || e.Exception is System.Net.Sockets.SocketException)
|
||||||
if (!(e.Exception is SshConnectionException))
|
|
||||||
{
|
|
||||||
Debug.Console(1, this, "Disconnected by remote");
|
Debug.Console(1, this, "Disconnected by remote");
|
||||||
}
|
else
|
||||||
if (Client != null)
|
Debug.Console(1, this, "Unhandled SSH client error: {0}", e.Exception);
|
||||||
{
|
|
||||||
Client.Disconnect();
|
|
||||||
//Client.Dispose();
|
|
||||||
//Client = null;
|
|
||||||
}
|
|
||||||
ClientStatus = SocketStatus.SOCKET_STATUS_BROKEN_REMOTELY;
|
ClientStatus = SocketStatus.SOCKET_STATUS_BROKEN_REMOTELY;
|
||||||
HandleConnectionFailure();
|
HandleConnectionFailure();
|
||||||
}
|
}
|
||||||
@@ -397,12 +421,8 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void OnConnectionChange()
|
void OnConnectionChange()
|
||||||
{
|
{
|
||||||
//if(ConnectionChange != null)
|
if (ConnectionChange != null)
|
||||||
// ConnectionChange(this, new SshConnectionChangeEventArgs(IsConnected, this));
|
ConnectionChange(this, new GenericSocketStatusChageEventArgs(this));
|
||||||
|
|
||||||
var handler = SocketStatusChange;
|
|
||||||
if (handler != null)
|
|
||||||
SocketStatusChange(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IBasicCommunication Members
|
#region IBasicCommunication Members
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ namespace PepperDash.Core
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event GenericSocketStatusChangeEventDelegate SocketStatusChange;
|
//public event GenericSocketStatusChangeEventDelegate SocketStatusChange;
|
||||||
|
public event EventHandler<GenericSocketStatusChageEventArgs> ConnectionChange;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
@@ -207,10 +208,14 @@ namespace PepperDash.Core
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relay the event
|
var handler = ConnectionChange;
|
||||||
var handler = SocketStatusChange;
|
|
||||||
if (handler != null)
|
if (handler != null)
|
||||||
SocketStatusChange(this);
|
ConnectionChange(this, new GenericSocketStatusChageEventArgs(this));
|
||||||
|
|
||||||
|
// Relay the event
|
||||||
|
//var handler = SocketStatusChange;
|
||||||
|
//if (handler != null)
|
||||||
|
// SocketStatusChange(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace PepperDash.Core
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISocketStatus : IBasicCommunication
|
public interface ISocketStatus : IBasicCommunication
|
||||||
{
|
{
|
||||||
event GenericSocketStatusChangeEventDelegate SocketStatusChange;
|
event EventHandler<GenericSocketStatusChageEventArgs> ConnectionChange;
|
||||||
SocketStatus ClientStatus { get; }
|
SocketStatus ClientStatus { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,11 +32,7 @@ namespace PepperDash.Core
|
|||||||
|
|
||||||
static CTimer SaveTimer;
|
static CTimer SaveTimer;
|
||||||
|
|
||||||
/// <summary>
|
static Debug()
|
||||||
/// This should called from the ControlSystem Initiailize method. Will attempt to call
|
|
||||||
/// CrestronDataStoreStatic.InitCrestronDataStore which may have been called elsewhere.
|
|
||||||
/// </summary>
|
|
||||||
public static void Initialize()
|
|
||||||
{
|
{
|
||||||
CrestronDataStoreStatic.InitCrestronDataStore();
|
CrestronDataStoreStatic.InitCrestronDataStore();
|
||||||
if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro)
|
if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro)
|
||||||
@@ -53,6 +49,27 @@ namespace PepperDash.Core
|
|||||||
Level = Contexts.GetOrCreateItem("DEFAULT").Level;
|
Level = Contexts.GetOrCreateItem("DEFAULT").Level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This should called from the ControlSystem Initiailize method. Will attempt to call
|
||||||
|
/// CrestronDataStoreStatic.InitCrestronDataStore which may have been called elsewhere.
|
||||||
|
/// </summary>
|
||||||
|
public static void Initialize()
|
||||||
|
{
|
||||||
|
//CrestronDataStoreStatic.InitCrestronDataStore();
|
||||||
|
//if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro)
|
||||||
|
//{
|
||||||
|
// // Add command to console
|
||||||
|
// CrestronConsole.AddNewConsoleCommand(SetDebugFromConsole, "appdebug",
|
||||||
|
// "appdebug:P [0-2]: Sets the application's console debug message level",
|
||||||
|
// ConsoleAccessLevelEnum.AccessOperator);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler;
|
||||||
|
|
||||||
|
//LoadMemory();
|
||||||
|
//Level = Contexts.GetOrCreateItem("DEFAULT").Level;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Used to save memory when shutting down
|
/// Used to save memory when shutting down
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Binary file not shown.
@@ -2,6 +2,6 @@
|
|||||||
<ControlSystem>
|
<ControlSystem>
|
||||||
<Name>MC3 SSH</Name>
|
<Name>MC3 SSH</Name>
|
||||||
<Address>ssh 10.0.0.15</Address>
|
<Address>ssh 10.0.0.15</Address>
|
||||||
<ProgramSlot />
|
<ProgramSlot>Program01</ProgramSlot>
|
||||||
<Storage />
|
<Storage>Internal Flash</Storage>
|
||||||
</ControlSystem>
|
</ControlSystem>
|
||||||
Binary file not shown.
@@ -10,8 +10,8 @@
|
|||||||
<ArchiveName />
|
<ArchiveName />
|
||||||
</RequiredInfo>
|
</RequiredInfo>
|
||||||
<OptionalInfo>
|
<OptionalInfo>
|
||||||
<CompiledOn>11/28/2016 1:59:52 PM</CompiledOn>
|
<CompiledOn>12/6/2016 4:09:28 PM</CompiledOn>
|
||||||
<CompilerRev>1.0.0.25195</CompilerRev>
|
<CompilerRev>1.0.0.29083</CompilerRev>
|
||||||
</OptionalInfo>
|
</OptionalInfo>
|
||||||
<Plugin>
|
<Plugin>
|
||||||
<Version>Crestron.SIMPLSharp, Version=2.0.48.0, Culture=neutral, PublicKeyToken=812d080f93e2de10</Version>
|
<Version>Crestron.SIMPLSharp, Version=2.0.48.0, Culture=neutral, PublicKeyToken=812d080f93e2de10</Version>
|
||||||
|
|||||||
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
MainAssembly=PepperDash_Core.dll:91882e81937f6bb6c3592368dedeea09
|
MainAssembly=PepperDash_Core.dll:987a92dfd5c1b46ff22b2570acef6436
|
||||||
MainAssemblyMinFirmwareVersion=1.007.0017
|
MainAssemblyMinFirmwareVersion=1.007.0017
|
||||||
MainAssemblyResource=SimplSharpData.dat:315526abf906cded47fb0c7510266a7e
|
MainAssemblyResource=SimplSharpData.dat:315526abf906cded47fb0c7510266a7e
|
||||||
ü
|
ü
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user