Between family visiting, having people move, and "disasters" at work, working on anything of my own has taken a back seat. That being said, I did have enough time to write some code to help with a project I was working on though. At work we ended up getting these Cisco phones. And since you can program for them, I was told I had a new project (I believe the exact quote from my boss was "Figure out what the hell we can do with it."). Anyway, I downloaded Cisco's SDK and looked through their examples... Not a single ASP.Net app... Some ASP and Java apps, but nothing in the .Net realm. So I created my own set of classes to help me out:
/*
Copyright (c) 2010 <a href="http://www.gutgames.com">James Craig</a>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.*/
#region Usings
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Utilities.Cisco.Interfaces;
#endregion
namespace Utilities.Cisco
{
/// <summary>
/// Text class
/// </summary>
public class Text:IDisplay
{
#region Constructor
/// <summary>
/// Constructor
/// </summary>
public Text()
{
SoftKeys = new List<SoftKeyItem>();
}
#endregion
#region Properties
/// <summary>
/// Title
/// </summary>
public string Title { get; set; }
/// <summary>
/// Prompt
/// </summary>
public string Prompt { get; set; }
/// <summary>
/// Text
/// </summary>
public string Content { get; set; }
/// <summary>
/// Softkey list
/// </summary>
public List<SoftKeyItem> SoftKeys { get; set; }
#endregion
#region Public Overridden Functions
public override string ToString()
{
StringBuilder Builder = new StringBuilder();
Builder.Append("<CiscoIPPhoneText><Title>").Append(Title).Append("</Title><Prompt>")
.Append(Prompt).Append("</Prompt><Text>").Append(Content).Append("</Text>");
foreach (SoftKeyItem Item in SoftKeys)
{
Builder.Append(Item.ToString());
}
Builder.Append("</CiscoIPPhoneText>");
return Builder.ToString();
}
#endregion
}
}
It turns out that all the Cisco phone is looking for is an XML file. Each type of display item has it's own format (a listing for each of them can be found here). That being said, the code above creates text, which can be displayed on the screen. It inherits from the IDisplay interface, which simply holds a list of soft keys. Soft keys is basically an input from the user:
/*
Copyright (c) 2010 <a href="http://www.gutgames.com">James Craig</a>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.*/
#region Usings
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#endregion
namespace Utilities.Cisco
{
/// <summary>
/// Softkey class
/// </summary>
public class SoftKeyItem
{
#region Constructor
/// <summary>
/// Constructor
/// </summary>
public SoftKeyItem()
{
}
#endregion
#region Properties
/// <summary>
/// Name of the softkey
/// </summary>
public string Name { get; set; }
/// <summary>
/// URL action for release event
/// </summary>
public string URL { get; set; }
/// <summary>
/// URL action for press event
/// </summary>
public string URLDown { get; set; }
/// <summary>
/// position of softkey
/// </summary>
public int Position { get; set; }
#endregion
#region Overridden Functions
public override string ToString()
{
StringBuilder Builder = new StringBuilder();
Builder.Append("<SoftKeyItem><Name>").Append(Name).Append("</Name><URL>").Append(URL).Append("</URL><URLDown>")
.Append(URLDown).Append("</URLDown><Position>").Append(Position).Append("</Position></SoftKeyItem>");
return Builder.ToString();
}
#endregion
}
}
Basically a soft key has a name, an action URL when pressed or an action URL when released/clicked, and a position within the list of softkeys. And they're able to be used in conjunction with any display item. Speaking of display items, there are a number of them and depending on the model of your phone, different ones are useable. For instance, I have a 7965 at work. As such I have access to pretty much everything, but earlier phones may have less features available. Anyway, after learning all of this I decided the best thing to do was to create a basic weather app. It's simple enough but for some reason people get excited about things like that. So I created a new web app, created a new webpage, and sstarted working:
namespace Cisco
{
public partial class _Default : System.Web.UI.Page
{
private static string ServerImage="ServerImagePath";
private static string ServerIP = "ServerPath";
protected void Page_Load(object sender, EventArgs e)
{
if (!Utilities.FileManager.FileExists(Server.MapPath("~/Weather/Images/Image2.png"))
|| File.GetCreationTime(Server.MapPath("~/Weather/Images/Image2.png")) < DateTime.Now.AddHours(-1))
{
string Content = Utilities.FileManager.GetFileContents(new Uri("http://rss.weather.com/weather/rss/local/")); //Note that you need to get the RSS Feed for your area and plug it in here
XmlDocument XmlDocument = new XmlDocument();
XmlDocument.LoadXml(Content);
Utilities.FileFormats.RSSHelper.Document Document = new Utilities.FileFormats.RSSHelper.Document(XmlDocument);
string Description = Document.Channels[0].Items[0].Description;
Regex TempReg = new Regex("<img src=\"(?<URL>[^\"]*)\"(.*)/>(?<TEXT>(.*))");
MatchCollection Matches = TempReg.Matches(Description);
string Text = "";
foreach (Match Match in Matches)
{
Text = Match.Groups["TEXT"].Value.Replace("anddeg;", "").Replace("For more details?", "").Replace(", and", "\n").Replace(".", "");
}
Utilities.Media.Image.Image.DrawText(Server.MapPath("~/Weather/Images/Image.png"), Server.MapPath("~/Weather/Images/Image2.png"), Text, new Font("Arial", 16f), Brushes.White, new RectangleF(179, 45, 90, 80));
}
Response.ContentType = "text/xml";
Utilities.Cisco.Image Image = new Utilities.Cisco.Image();
Image.Title = "Weather";
Image.Prompt = "Weather";
Image.URL = "http://" + ServerImage + "/Image2.png";
Image.X = 0;
Image.Y = 0;
Response.Write(Image.ToString());
Response.End();
}
}
}
The code above is the actual web page's code. All we're doing is double checking the last time we updated the image. If it has been more than an hour, we pull our local weather feed from weather.com (or whomever you want as you'll need to replace that location with your own), getting the first item from the RSS feed, and pulling out the text saying what temperature it is and whether it is sunny, partly cloudy, raining, etc. From there we take a default image that we choose and write the text on it, saving it in a new location. We then use the Image class (which I'll show you in a second) to export that as an XML doc that the phone will recognize. And that's it. The RSSHelper, FileManager, and Image classes are all found in my utility library. The Cisco Image class on the other hand can be found here:
/*
Copyright (c) 2010 <a href="http://www.gutgames.com">James Craig</a>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.*/
#region Usings
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Utilities.Cisco.Interfaces;
#endregion
namespace Utilities.Cisco
{
/// <summary>
/// Image class
/// </summary>
public class Image:IDisplay
{
#region Constructor
/// <summary>
/// Constructor
/// </summary>
public Image()
{
SoftKeys = new List<SoftKeyItem>();
}
#endregion
#region Properties
/// <summary>
/// Title
/// </summary>
public string Title { get; set; }
/// <summary>
/// Prompt
/// </summary>
public string Prompt { get; set; }
/// <summary>
/// X location
/// </summary>
public int X { get; set; }
/// <summary>
/// Y location
/// </summary>
public int Y { get; set; }
/// <summary>
/// URL to the image
/// </summary>
public string URL { get; set; }
/// <summary>
/// Softkeys list
/// </summary>
public List<SoftKeyItem> SoftKeys { get; set; }
#endregion
#region Overridden Functions
public override string ToString()
{
StringBuilder Builder = new StringBuilder();
Builder.Append("<CiscoIPPhoneImageFile><Title>").Append(Title).Append("</Title><Prompt>").Append(Prompt).Append("</Prompt><LocationX>")
.Append(X.ToString()).Append("</LocationX><LocationY>").Append(Y.ToString()).Append("</LocationY><URL>")
.Append(URL).Append("</URL>");
foreach (SoftKeyItem Item in SoftKeys)
{
Builder.Append(Item.ToString());
}
Builder.Append("</CiscoIPPhoneImageFile>");
return Builder.ToString();
}
#endregion
}
}
It simply wants to know the title, prompt, location of the image, and the URL pointing to it and in return spits out a bit of XML for the phone. Also note that you have to use png files. The phone doesn't work with any other format really, so make sure to convert them over. It's incredibly simple once you jump into it. But that's all I had to do in order to get weather on my phone. If you want the rest of the helpers that I created, you can go here and download them from the utility library's source code. Note that certain elements I didn't include as I didn't need them (I would rather deal with images than individual pixels personally). That being said, you can actually create some nice apps rather quickly for it using the code and you can create items rather quickly to fill in the gaps. So give it a try, leave feedback, and happy coding.
63a1c2a0-489f-47c4-b473-5302a9b42f82|0|.0