воскресенье, 29 августа 2010 г.

Часть 4:Система удаленного управления приложениями персонального компьютера с помощью мобильных устройств

В результате работы, описанной в статьях раннее, была спроектирована система, абстрагированная от среды передачи данных и модульная, позволяющая разработчикам создавать собственные расширения, покрывая недостающую функциональность и обеспечивая поддержку новых приложений, а так же позволяя разрабатывать модули работы с появляющимися новыми или редкими средами передачи данных. Так же, в рамках данной работы, было разработано тестовое приложение, демонстрирующее работу системы и являющееся в какой-то мере, обучающим, показывающим формат сообщений, которыми обмениваются сервер и клиент.
В дальнейшем, планируется добавление новой функциональности, такой, как обмен сервера и клиента сообщениями в формате XML, реализация Bluetooth сервиса, возможность возврата плагином не только текстовой информации, но и информации других типов, например, изображений, реализация "обратного сообщения", то есть управление мобильным устройством, например КПК, с помощью компьютера.
Далее я приведу исходные коды разработанного приложения.

Код класса UIEngine

using System;
using System.Windows.Forms;
using System.Drawing;
using rpcmsdk;
namespace ControllerServer
{
public class UIEngine
{
private MainForm mainForm;
private ClientsForm clientsForm;
private HelpForm helpForm;
private PluginsForm pluginsForm;
private static UIEngine instance;
public static UIEngine Instance
{
get
{
if (instance == null) instance = new UIEngine();
return instance;
}
}
private UIEngine()
{
//
// TODO: Add constructor logic here
//
Engine.Instance.ServerStarted += new EventHandler(engine_ServerStarted);
Engine.Instance.ServerStopped +=new EventHandler(engine_ServerStopped);
Engine.Instance.ClientConnected += new EventHandler(engine_ClientConnected);
Engine.Instance.PluginsLoaded +=new EventHandler(engine_PluginsLoaded);
Engine.Instance.ClientDisconnected += new EventHandler(engine_ClientDisconnected);
}
public void Run()
{
Logger.Instance.LogToConsole("UIEngine.Run:");
mainForm = new MainForm();
mainForm.Show();
mainForm.mainFormToolBar.ButtonClick += new ToolBarButtonClickEventHandler(mainFormToolBar_ButtonClick);
clientsForm = new ClientsForm();
helpForm = new HelpForm();
pluginsForm = new PluginsForm();
}
private void engine_ClientConnected(object sender, EventArgs e)
{
Client client = e as Client;
ClientListViewItem lvi = new ClientListViewItem();
lvi.Text = "Client";
lvi.Client = client;
lvi.SubItems.Add(client.GetService().GetName());
lvi.SubItems.Add(client.GetDescription());
clientsForm.clientListView.Items.Add(lvi);
}
private void mainFormToolBar_ButtonClick(object sender, ToolBarButtonClickEventArgs e)
{
if (e.Button == mainForm.startToolBarButton)
{
startStopServer(e.Button);
}
if (e.Button == mainForm.clientsToolBarButton)
{
clientsForm.Visible = true;
}
if (e.Button == mainForm.pluginsToolBarButton)
{
pluginsForm.Visible = true;
}
if (e.Button == mainForm.helpToolBarButton)
{
//helpForm.Visible = true;
helpForm.ShowDialog();
}
if (e.Button == mainForm.minimizeToolBarButton)
{
mainForm.Visible = false;
clientsForm.lastVisible = clientsForm.Visible;
clientsForm.Visible = false;
helpForm.lastVisible = helpForm.Visible;
helpForm.Visible = false;
}
if (e.Button == mainForm.closeToolBarButton)
{
Engine.Instance.StopServer();
Application.Exit();
}
}
private void startStopServer(ToolBarButton button)
{
if (!Engine.Instance.Started)
{
//engine.LoadPlugins();
button.ImageIndex = 1;
button.Pushed = true;
Engine.Instance.LoadPlugins();
//serverStarted = engine.StartServer();
Engine.Instance.StartServer();
}
else
{
//engine.StopServer();
DialogResult dr = MessageBox.Show("Are you sure?","Stop Server",MessageBoxButtons.YesNo , MessageBoxIcon.Question);
if (dr == DialogResult.Yes)
{
Engine.Instance.StopServer();
}
}
// TODO THIS CAN BE PLACED INTO Engine.Started and Engine.Stopped handlers
if (Engine.Instance.Started)
{
//Icon i = new Icon("green.ico");
Icon i = new Icon(this.GetType().Assembly.GetManifestResourceStream("ControllerServer.Resources.green.ico"));
mainForm.mainNotifyIcon.Icon = i;
//startBtn.Text = XRes.GetString("STOP_SERVER_BTN");
//startBtn.BackColor = Color.LightCoral;
}
else
{
//Icon i = new Icon("red.ico");
Icon i = new Icon(this.GetType().Assembly.GetManifestResourceStream("ControllerServer.Resources.red.ico"));
mainForm.mainNotifyIcon.Icon = i;
button.ImageIndex = 0;
button.Pushed = false;
//startBtn.Text = XRes.GetString("START_SERVER_BTN");
//startBtn.BackColor = Color.MediumSpringGreen;
}
}
private void engine_PluginsLoaded(object sender, EventArgs e)
{
pluginsForm.pluginsListView.Items.Clear();
RPCMPluginHolder[] phArr = Engine.Instance.Plugins;
ListViewItem lvi = null;
foreach (RPCMPluginHolder ph in phArr)
{
lvi = new ListViewItem();
lvi.Text = ph.Name;
lvi.SubItems.Add(ph.GUID);
String commands = "";
foreach (String s in ph.CommandsList)
{
commands += s + "; ";
}
lvi.SubItems.Add(commands);
lvi.SubItems.Add(ph.Description);
lvi.SubItems.Add(ph.About);
pluginsForm.pluginsListView.Items.Add(lvi);
}
}
private void engine_ServerStarted(object sender, EventArgs e)
{
}
private void engine_ServerStopped(object sender, EventArgs e)
{
pluginsForm.pluginsListView.Items.Clear();
clientsForm.clientListView.Items.Clear();
}
private void engine_ClientDisconnected(object sender, EventArgs e)
{
Client client = e as Client;
if (client == null) return;
foreach (ClientListViewItem clvi in clientsForm.clientListView.Items)
{
if (client.Equals(clvi.Client))
{
clientsForm.clientListView.Items.Remove(clvi);
}
}
}
}
}


Код класса Engine

using System;
using System.Collections;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Net.Sockets;
using rpcmsdk;
namespace ControllerServer
{
/// <summary>
/// Summary description for Engine.
/// </summary>
public class Engine
{
public event EventHandler PluginsLoaded;
public event EventHandler ClientConnected;
public event EventHandler ClientDisconnected;
public event EventHandler ServerStarted;
public event EventHandler ServerStopped;
private event EventHandler DataReceived;
private EventHandler dataSendRequiredEventHandler;
private Thread watchDogThread;
private bool started;
public bool Started
{
get
{
return started;
}
}
//private LANService ls;
private ArrayList clientsAL;
//private NetworkDataParser dataParser;
private static Engine instance;
public static Engine Instance
{
get
{
if (instance == null) instance = new Engine();
return instance;
}
}
public RPCMPluginHolder[] Plugins
{
get
{
return pluginsAL == null ? null : (RPCMPluginHolder[])(pluginsAL.ToArray(typeof(RPCMPluginHolder)));
}
}
private ArrayList pluginsAL;
private ArrayList servicesAL;
private Engine()
{
//
// TODO: Add constructor logic here
//
//dataParser = new NetworkDataParser();
dataSendRequiredEventHandler = new EventHandler(DataSendRequiredHandler);
clientsAL = new ArrayList();
servicesAL = new ArrayList();
}
public void OnClientConnected(EventArgs e)
{
if(ClientConnected != null)
ClientConnected(this, e);
}
public void OnClientDisconnected(EventArgs e)
{
Client client = e as Client;
clientsAL.Remove(client);
client.CloseConnection();
if(ClientDisconnected != null)
ClientDisconnected(this, e);
}
public void OnPluginsLoaded(EventArgs e)
{
Logger.Instance.LogToConsole("Engine.OnPluginsLoaded");
if(PluginsLoaded != null)
PluginsLoaded(this, e);
}
public void OnServerStarted(EventArgs e)
{
if(ServerStarted != null)
ServerStarted(this, e);
}
public void OnServerStopped(EventArgs e)
{
if(ServerStopped != null)
ServerStopped(this, e);
}
public bool StartServer()
{
System.GC.Collect();
started = false;
Logger.Instance.LogToConsole("Engine.ServerStart");
/*ls = new LANService();
//Safe because it is safe in LANService.Stop()
ls.ClientConnected += new EventHandler(ClientConnectedHandler);
ls.Initialize();
started = started || ls.Start();*/
LoadServices();
if (servicesAL != null)
foreach(RPCMNetworkService ns in servicesAL)
{
started = ns.Start() | started;
}
watchDogThread = new Thread(new ThreadStart(WatchDogThreadProc));
watchDogThread.Start();
OnServerStarted(null);
return started;
}
public void StopServer()
{
started = false;
//if (ls != null) ls.Stop();
if (clientsAL != null)
foreach(Client client in clientsAL)
{
if (client != null)
client.CloseConnection();
}
clientsAL.Clear();
if (servicesAL != null)
foreach(RPCMNetworkService ns in servicesAL)
{
ns.Stop();
}
if (watchDogThread != null && watchDogThread.IsAlive) watchDogThread.Interrupt();
OnServerStopped(null);
}
public void LoadServices()
{
//if (servicesAL != null)
/*foreach (RPCMPluginHolder ph in pluginsAL)
{
ph.Plugin.DataSendRequired -= dataSendRequiredEventHandler;
}*/
// PluginHolder objects are not deleted if handler link is alive
//DataReceived = null;
DirectoryInfo di = new DirectoryInfo(Application.StartupPath+"\\services\\");
FileInfo[] fiarr = di.GetFiles("*.dll");
servicesAL = new ArrayList();
foreach (FileInfo fi in fiarr)
{
try
{
Assembly a = Assembly.LoadFrom(fi.FullName);
foreach (Type t in a.GetExportedTypes())
{
System.Console.WriteLine(t.Name);
}
RPCMNetworkService ns = (RPCMNetworkService)a.CreateInstance("RPCMNetworkServiceNamespace.RPCMNetworkServiceInstance", true);
ns.ClientConnected += new EventHandler(ClientConnectedHandler);
servicesAL.Add(ns);
ns.Initialize();
}
catch (Exception ex)
{
Logger.Instance.LogException(ex);
Logger.Instance.PopupErrorMessage(/*MainForm.XRes.GetString(*/"CANT_LOAD_PLUGIN"/*)*/ + "\n" +fi.FullName);
}
}
}
public void UnloadServices()
{
}
public void LoadPlugins()
{
if (pluginsAL != null)
foreach (RPCMPluginHolder ph in pluginsAL)
{
ph.Plugin.DataSendRequired -= dataSendRequiredEventHandler;
}
// PluginHolder objects are not deleted if handler link is alive
DataReceived = null;
DirectoryInfo di = new DirectoryInfo(Application.StartupPath+"\\plugins\\");
FileInfo[] fiarr = di.GetFiles("*.dll");
pluginsAL = new ArrayList();
foreach (FileInfo fi in fiarr)
{
try
{
Assembly a = Assembly.LoadFrom(fi.FullName);
foreach (Type t in a.GetExportedTypes())
{
System.Console.WriteLine(t.Name);
}
RPCMPlugin p = (RPCMPlugin)a.CreateInstance("RPCMPluginNamespace.RPCMPluginInstance", true);
DataReceived += new EventHandler(p.DataReceivedHandler);
p.DataSendRequired += dataSendRequiredEventHandler/*new EventHandler(DataSendRequiredHandler)*/;
RPCMPluginHolder ph = new RPCMPluginHolder(p);
pluginsAL.Add(ph);
}
catch (Exception ex)
{
Logger.Instance.LogException(ex);
Logger.Instance.PopupErrorMessage(/*MainForm.XRes.GetString(*/"CANT_LOAD_PLUGIN"/*)*/ + "\n" +fi.FullName);
}
}
OnPluginsLoaded(null);
}
public void ClientConnectedHandler(object sender, EventArgs e)
{
Client client = e as Client;
client.DataBytesReceived += new DataBytesReceivedHandler(DataBytesReceived);
clientsAL.Add(client);
OnClientConnected(client);
Logger.Instance.LogToConsole("Engine: Client Connected! " + client.ToString());
}
public void DataBytesReceived(object sender, byte[] dataBytes)
{
Logger.Instance.LogToConsole("Engine.DataBytesReceived");
//Monitor.Wait(dataParser);
//Monitor.Enter(dataParser);
RPCMData data = NetworkDataParser.BytesToData(dataBytes);
HandleData(sender as Client, data);
if (DataReceived != null)
DataReceived(sender as Client, data);
//Monitor.Exit(dataParser);
//Monitor.Pulse(dataParser);
}
private void HandleData(Client client,RPCMData data)
{
Logger.Instance.LogToConsole("Engine.HandleData");
//TODO
if (data == null) return;
if (data.MessageType == (int)MessageTypes.Test)
{
Logger.Instance.LogToConsole("Engine.HandleData: data.MessageType == Test");
client.SendData(new byte[4]{(byte)'t',(byte)'e',(byte)'s',(byte)'t'});
}
if (data.MessageType == (int)MessageTypes.PluginsDescriptionRequired)
{
Logger.Instance.LogToConsole("Engine.HandleData: data.MessageType == PluginDescriptionRequired");
RPCMPluginHolder[] pluginsHolders = this.Plugins;
int count = pluginsHolders.Length;
RPCMData dataToSend = null;
for (int i = 0; i < count; i++)
{
dataToSend = new RPCMData();
dataToSend.GUID = pluginsHolders[i].GUID;
dataToSend.MessageType = (int)MessageTypes.PluginDescription;
String description = pluginsHolders[i].Name + "#" + pluginsHolders[i].Description;
int counter = pluginsHolders[i].CommandsList.Length;
for (int j = 0; j < counter; j++ )
{
description += "#"+pluginsHolders[i].CommandsList[j];
}
dataToSend.DataArr = new byte[description.Length];
/*char[] descriptionCh = description.ToCharArray();
for (int j = 0; j < description.Length; j++)
{
dataToSend.DataArr[j] = (byte)descriptionCh[i];
}*/
dataToSend.DataArr = RPCMArrayConverter.CharArrToByteArr(description.ToCharArray());
Logger.Instance.LogToConsole("Engine.HandleData: " + description);
Logger.Instance.LogToConsole("Engine.HandleData: " + new String(RPCMArrayConverter.ByteArrToCharArr(dataToSend.DataArr)));
byte[] dataBytes = NetworkDataParser.DataToBytes(dataToSend);
client.SendData(dataBytes);
}
}
}
private void DataSendRequiredHandler (object sender, EventArgs e)
{
RPCMData data = null;
try
{
Logger.Instance.LogToConsole("Engine.DataSendRequiredHandler");
data = e as RPCMData;
if (sender == null || e == null) return;
if (data.Client != null)
{
Logger.Instance.LogToConsole("Engine.DataSendRequiredHandler: Send Data To Client");
data.Client.SendData(NetworkDataParser.DataToBytes(data));
}
}
catch(ConnectionClosedException)
{
OnClientDisconnected(data.Client);
}
catch(Exception ex)
{
Logger.Instance.LogException(ex);
Logger.Instance.PopupErrorMessage(ex.Message);
}
}
private void WatchDogThreadProc()
{
try
{
Logger.Instance.LogToConsole("Engine.WatchDogThreadProc");
while(true)
{ Logger.Instance.LogToConsole("Engine.WatchDogThreadProc: Cycle");
Thread.Sleep(5000);
if (clientsAL == null) return;
Client[] clients = (Client[])clientsAL.ToArray(typeof(Client));
//foreach (Client client in clientsAL)
for (int i = 0; i < clients.Length ; i++)
{
try
{
RPCMData data = new RPCMData();
data.GUID = "00000000000000000000000000000000";
data.MessageType = (int)MessageTypes.Test;
data.DataArr = new byte[4]{(byte)'t',(byte)'e',(byte)'s',(byte)'t'};
clients[i].SendData(NetworkDataParser.DataToBytes(data));
Logger.Instance.LogToConsole("Engine.WatchDogThreadProc: Client " + clients[i].ToString() + " SendData");
}
catch(ConnectionClosedException/* ex*/)
{
//Logger.Instance.LogToConsole(ex.Message + " " + ex.ErrorCode.ToString());
OnClientDisconnected(clients[i]);
}
}
}
}
catch (ThreadInterruptedException)
{
}
catch (Exception ex)
{
Logger.Instance.LogException(ex);
Logger.Instance.PopupErrorMessage(ex.Message);
}
}
}
}

Комментариев нет:

Отправить комментарий