Download RestWebServer.zip - 3.44 KB
Introduction
The Idea of presenting media on a screen using the mobile phones and QR-codes came up during a brainstorm meeting. There was a need to visualize information of our projects in some interactive way. With information and QR-codes printed on traditional paper sheets together with an interactive flat screen, the result would probable give the visitor some extra curiosity.
An example of a application is a screen connected to a computer with the
server application below. On the server you put four different movies.
Under the screen you put four QR-codes corresponding to each movie. The
visitor can then scan the QR-code with his/her mobile phone and start
the corresponding movie on the screen.
To achieve this the server side would need some HTTP web server that listens for HTTP calls and open a file or application locally on the server. The server is then connected to a screen where the chosen application/movie/picture/presentation is shown. The only information possible to store in an QR-code and usable for this purpose is an url string. Therefor the HTTP server has to be able to open files provided in an URL string, using the REST architecture.
The HTTP has also to be started by an active computer user. If this would be implemented as service it would not be possible to show anything on a normally configured screen connection in Windows.
The big pros with this approach is that QR-cdes can easily be read by a mobile phone that you always have
available. In an exhibition you often want to interact with the system,
Extra hardware for integration is expensive. Instead you can use your
visitors mobile device as the tool. The only thing you would need is to buy a cheep computer and connect
that to a fancy screen. Then you let you visitors scan QR-codes to
answering questions, start movies, start presentations or what ever.
The files that is allowed to be opened is defined in the code as a folder. To open a file in the folder the file name is provided within the arguments provided in the http rest call. e.g. http://Myserver:8080/?file=openme.txt
Using the code
The code is simple and configurable depending on how you want to show your files. For movies and PowerPoint I send arguments to expand the media to full screen. Please refer to the specific software's manual to get the know how to interact with the software.
To create a QR-code that will be used for starting an application you use any QR-creator available on internet, e.g. http://qrcode.kaywa.com/. For the connection string you need the adress or ip to the server, the port used, and the file or homepage to show on server-side, e.i:
http://your-address:your-port/?file=your-file
To start the server side application you start the exe file in administration mode, (needed to listen to ports, at least for me). The default port is 8080 and is changed either in the code or by giving the port as an argument. e.g. create a shortcut and specify the port in the command field for the shortcut properties.
I added support for steaming videos to the requesting device. this is done by adding the argument local=true to the rest call, e.i.
http://your-address:your-port/?file=your-file&local=true
The Code
The main loop basically starts a HttpListener and answer all calls by calling StartProgram with the file provided in the REST argument and respond by "Started" or a exception if the file did not exist or any exception occur.
private static string httpfilesource = "http://desenergy.selfip.org/";
private static string filefolder = "C:\\Videos\\";
private static void Main(string[] args)
{
var server = new HttpListener();
int port;
if (args != null && args.Length > 0 && int.TryParse(args[0], out port))
server.Prefixes.Add(@"http: else
server.Prefixes.Add(@"<a href="http: while (true)
{
server.Start();
HttpListenerContext context = server.GetContext();
NameValueCollection query = context.Request.QueryString;
bool local = false;
string file = query["file"];
if (query["local"] != null)
local = "true".ToLowerInvariant() == query["local"].ToLowerInvariant();
string exc = "";
string responseString = "";
try
{
if (file != null)
{
if (local)
{
responseString = "<HTML><BODY><video width=\"320\" height=\""
+ "240\" controls=\"controls\">"
+ "<source src=\"" + httpfilesource + file
+ "\" type=\"video/ogg\" />"
+ "Your browser does not support the video tag."
+ "</video></BODY></HTML>";
}
else
{
StartProgram(filefolder + file);
responseString = "<HTML><BODY> Startad </BODY></HTML>";
}
}
}
catch (Exception e)
{
exc = e.ToString();
}
HttpListenerResponse response = context.Response;
if (exc != "")
responseString = "<HTML><BODY> Exception =" + exc + " </BODY></HTML>";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
}
}
The next step is to implement the StartProgram function.
Files provided to the StartProgram function is by default executed by the server. Windows file association will take care of how to execute the file. However, in this implementation i need to start some files in full screen, e.g. start movies, Powerpoints, WordFiles and homepages in full screen from start.
To achieve the full screen the application sends start argument to the actual application itself. The arguments send depend on the application used, but the actual document or media is always provided as one of the arguments.
The default programs for the special programs is defined in constant strings. Be aware that the strings to open specific programs differs from installation to installation. If you want a more rigid design you can access the registry to get the file folders.
The method basically first clean the filename for some problems with Nordic letters, then analyses the string and start it with the correct application. If there is no default application for the file type, the application try to start the file it self.
private const String Reader = @"C:\Program Files (x86)\Adobe\Acrobat 10.0\Acrobat\Acrobat.exe";
private const String Explorer = @"C:\Program Files (x86)\Internet Explorer\iexplore.exe";
private const String PowerPoint = @"C:\Program Files (x86)\Microsoft Office\Office14\POWERPNT.EXE";
private const String WinWord = @"C:\Program Files (x86)\Microsoft Office\Office14\winword.exe";
private const String WMPlayer = @"C:\Program Files\Windows Media Player\wmplayer.exe";
private static void StartProgram(string s)
{
string file = String.Copy(s);
if (file != null)
{
file = file .Replace("ö", "ö");
file = file.Replace("ä", "ä");
file = file.Replace("Ã¥", "å");
}
string t;
try
{
t = file.Remove(0, file.LastIndexOf(".", StringComparison.Ordinal));
}
catch
{
t = s;
}
if (file.StartsWith("http://"))
{
StartProcess(Explorer,
"-k " + "\"" + file + "\"");
}
else
{
switch (t.ToLowerInvariant())
{
case ".ppt":
case ".pptx":
StartProcess(PowerPoint,
"/S " + "\"" + file + "\"");
break;
case ".doc":
case ".docx":
StartProcess(WinWord,
"/fullscreen " + "\"" + file + "\"");
break;
case ".mpg":
case ".mpeg":
case ".mp4":
case ".avi":
case ".ogg":
StartProcess(WMPlayer,
"\"" + file + "\"" + " /fullscreen");
break;
case ".pdf":
StartProcess(Reader,
"\"" + file + "\"");
break;
default:
StartProcess(file, null);
break;
}
}
}
The last part closes the previous process and and start the new one. The previous process is stored in an static field and can therefor be closed before the next process is started.
private static Process _process;
private static void StartProcess(string program, string argumentfile)
try
{
if (_process != null)
_process.CloseMainWindow();
}
catch (Exception)
{
}
_process = new Process
{
StartInfo =
{
FileName = program,
Arguments = argumentfile,
WindowStyle = ProcessWindowStyle.Maximized
}
};
_process.Start();
}
Points of Interest
If you do not want to open up your computers to the outside world you can have a open wireless network that provides the only way to connect to the servers.