Sometime between 4:30 pm yesterday and 8:00 am this morning (central time), the National Weather Service changed the format of their XML feed for forecast data. I don't yet know all of the details, but I know that the "time-layout" element no longer has a "period-name" attribute. If I can find any more information, I'll follow up on this post.
Sample XML feed
Schema
Thursday, September 3, 2009
Monday, August 10, 2009
Need references?
I've been working on an app at work that will update "slides" that we show on these huge LCD screens at each of the entrances to the building - things like the weather forecast, current tech news (since we're an IT training center), and where each class is located in the building.
It can be used either interactively or as a Scheduled Task (with the needed parameters passed as arguments in the command line). Until this morning, I've been running it myself from my laptop and updating the jpg's on the units manually about once a week. This really doesn't work for me. I'd much rather have the whole stupid process completely automated, but we're having some network issues that prevent the screens from communicating with our server room (UP&P is being blocked at the router). So until that is fixed (pr: circumvented), the jpg's have to be updated manually with a thumb drive.
Before I go any further, I should explain a little about what the app is actually doing. It opens a Powerpoint 2007 document, updates its content with information provided by the National Weather Server, Google News, and a web service from our local web server (for the course location information). Powerpoint really wasn't needed, but it did make it easier to design the slides.
So, like I said I've been running this from my laptop. I decided that it would be much better to try to put the executable right on the thumb drive and set it up so that anyone could use it. After copying the executable to a thumb drive I tried to run it from another computer (other than my laptop). I had already suspected that I would have some problems since the app is referencing the Powerpoint 2007 interop DLL, which is exactly what happened. Powerpoint 2007 had not been installed on this particular - I had chosen this set up on purpose to see what would happen.
So here was the question: How can I run this executable from a computer that doesn't have the Office 2007 DLL's on it, without having to acutally install this app?
Since I'm normally focused on Web apps, I haven't had to deal with this type of problem before. So after a little exploring in Visual Studio...
In Visual Studio, if you select the specific Reference in question (in this case the Office and Office.Powerpoint references), the IDE will expose several properties of the specific References in the Properties window. The one that I immediately focused on is called "Copy Local". This property indicates whether the reference will be copied to the output directory. After setting this option to "True" for both of the non-.NET DLL's, I rebuilt the app, copied the executable and both DLL's to the thumbdrive, and off to the "other" computer I went.
With the DLL's now in the startup folder of the executable, the app ran just fine. So next time you're at the ITTC, check out our new LCD screens powered by this little app.
Sunday, July 13, 2008
Adding URL's to email messages
I recently received a question from a co-worker about inserting URL's into emails. Although this isn't a normal topic of this site, I thought others might find it useful as well.
Josh,
I have a quick question. I am interested in how you made this a link.
I have copied and pasted the info but never been able turn it into a link.
Can you help me?
I have a quick question. I am interested in how you made this a link.
I have copied and pasted the info but never been able turn it into a link.
Can you help me?
file://P:/Information%20Technology%20Training%20Center\Public\SIAC%20Files\20
08-02-20%20Master%20Instructor%20rings.wmv
08-02-20%20Master%20Instructor%20rings.wmv
V/R,
Dana
Dana
Absolutely! Take the red pill and follow me down the rabbit hole...
Outlook will automatically create a link for any valid URL (Uniform Resource
Locator) that you type into an email. By definition, every URL must start with a protocol. The most common example of a protocol is seen in your address bar while surfing the Internet: http. Other examples of protocols include https, mailto, callto and file.
Locator) that you type into an email. By definition, every URL must start with a protocol. The most common example of a protocol is seen in your address bar while surfing the Internet: http. Other examples of protocols include https, mailto, callto and file.
In regards to the last one, let's say you want to create a URL that sends people to:
P:\Information Technology Training Center\Public\SIAC Files\
Keep in mind that the example above is not yet a URL, but it is only a file path. In order to create a URL from this path, the first thing you need to do is add a protocol at the beginning, like so:
file://P:\Information Technology Training Center\Public\SIAC Files\
Now you can see that the link was created, but it stops after the word "Information". This is not an error. This is because of another standard in URL's which states that there can be no spaces in a URL. There are a couple of ways that we could remove the spaces from this URL:
1. Rename the folders and files from "SIAC Files" to "SIAC_Files", etc.
2. Encode those spaces in our URL into Unicode.
2. Encode those spaces in our URL into Unicode.
The first option could be a major pain, and probably isn't worth the time, so let's look at the second option. While it might sound scary at first, encoding spaces into Unicode is very easy. Simply replace all of the spaces in the URL with %20. By doing this to our URL, it comes out looking like
this:
this:
And, viola, we have a properly formatted URL! Outlook, having realized this, has created the link for us.
Tuesday, May 27, 2008
The first date... ever.
I've been working on the third version of Vend-Trak for the past couple of weeks. We're going to incorporate Google Maps with directions, Google Charts (faster than the Java charts we've been using) and some other neat features. But really the biggest changes are all "behind the scenes".
Currently the application is written in ASP Classic (3.0) and is supported by a MySQL database. These choices were great at the time, and they served us well. But Vend-Trak has grown so much in the past few months that it's almost grown "too big for it's britches", as we say down here in Arkansas.
So that lead us to the decision that it is time for Vend-Trak to make the jump to ASP.Net. And we figured we might as well migrate to a full fledged Microsoft SQL Server while we were at it. This system-based relational database, along with the compiled ASP.Net application, should result in a MUCH faster application for the end-users. (I'll post the results when we're done.)
So that brings me to this blog. I knew that migrating from MySQL to SQL Server wouldn't be easy. But after some Googling I came across some helpful information. First, I needed to install the MySQL ODBC driver on my SQL Server so that I could pull the information from the old server. At that point I could create a "linked server" on the SQL Server by using a command similar to this:
EXEC master.dbo.sp_addlinkedserver @server = N'MYSQL', @srvproduct=N'MySQL', @provider=N'MSDASQL', @provstr=N'DRIVER={MySQL ODBC 3.51 Driver}; SERVER=127.0.0.1; DATABASE=ORIGINAL_DATABASE_NAME; USER=your_username; PASSWORD=your_password; OPTION=3'
Now that the MySQL server was linked from the SQL Server, I could copy each table from the original server to the new one with a single line:
Select * into newTable from openquery(MySQLServerName, 'select * from oldTable')
Up until this point it looks that maybe this won't be so bad after all. However, I hit a snag. After importing two of the 33 tables, I received this message:
Error converting data type DBTYPE_DBTIMESTAMP to datetime.
It took me several cups of coffee and lots of research to finally discover that MySQL's datetime datatype has a minimum value of January 1, 1000, while Microsoft SQL Server's datetime datatype begins with the first day of the year after the Gregorian calendar was put into use in British and American records: January 1, 1753. (Thanks to Peter Gulutzan and Trudy Pelzer for that tidbit of information.)
Now you might be thinking, "Josh, why is the world would you have dates in this database that are before January 1, 1753?" Well I'll tell you: inadequate error checking. When we provided inputs for users to be able to enter dates, we didn't consider that they would enter "8" as a year. Of course, when the users entered such a date and they didn't see the item that they just created on the calendar, then they created it a second time using VALID dates and got the expected result.
So, while there was a valid problem occuring, the end-users probably never realized that this was indeed a valid issue that needed to be reported, and we never considered that such a scenario was taking place.
I hope that this is useful to someone else and saves them from countless hours of frustration.
Wednesday, July 18, 2007
How to: Create "Web 2.0" graphics
Unless you've been under a rock for the past few months, you know that the "Web 2.0" look is becoming a very popular design on web sites. Web 2.0 isn't really the second version of the World Wide Web; this is a term that has been used to describe everything from AJAX-enabled web sites to the glossy, glass-like design that we'll be looking at in this article. This type of design can generally be recognized by it's glossy and beveled look. Most of the time, the subject ends up looking like a rounded piece of glass. In this article, I'll be showing you how to create your own Web 2.0 graphic with text. Here's an example of our final product:
For this tutorial I'll be using PhotoShop CS3, but you should be able to follow along with PhotoShop 6 or newer. So without any further ado, let's get crack-a-lackin!
To start off, you'll need to create a new document in PhotoShop. I'm going to start mine with a transparent background, width of 400 pixels and a height of 150 pixels (Screenshot).
In order to see what I'll be doing in the next few steps, I'm going to add a background now so that I have something to contract against. For that Web 2.0 feel I need to use a warm gradient for the background, so I'm going to use a gradient that transitions from black to dark green with the green on top (Screenshot).
Fig. 1 |
Next, you'll need to add the text that you want displayed. I've selected a 36pt, Strong, Arial Black font, then I've set the tracking (horizontal letter spacing) to -100 (Screenshot). This will bring the letters closer together, and will help the reflection and shadow to look more like part of the image later.
Fig. 2 |
Now we need to create the reflection of the text. First, create a copy of the layer that contains the text we added, by draging it down to the New Layer button in the Layers panel (Screenshot). Move the copied layer down a bit (so I can see it) then, with the copied layer still selected, flip it over by clicking on Edit »Transform » Flip Vertical.
Fig. 3 |
Before we can go any further with the reflection, you'll need to rasterize it: Right-click on the reflection layer and select Rasterize Type (Screenshot). Once the reflection has been rasterized, you can change the perspective by skewing it a little. Click on Edit » Transform » Skew, then drag the handles on the bottom left and right corners out, away from the text (Screenshot). Make sure that you try to drag them an equal distance from their original points.
Once you have finished skewing the text, select all of the pixels in that layer by holding down CTRL and clicking on the layer thumbnail in the layer window (Screenshot). Once the selection is loaded, hide the original reflection layer and create a new (blank) layer. Select the gradient tool and load a gradient that transitions from white to transparent (Screenshot).
With everything set up for it, now you can create the gradient that will be the reflection. Inside the (still) selected area, start the gradiant at the top of the selected area and have it end about 7/8 of the way down the tallest letter. The idea here is that the bottom edge of the tallest letters shouldn't be visible (Fig 4).
Fig. 4 |
To finish off the reflection, set back the opacity of the reflection layer to around 30% and move the reflection layer so that it meets the bottom of the original text (Fig 5).
Fig. 5 |
Now that we've finished the reflection all we have left is too create the shadow. For this, we'll need to use a technique that's a little more detailed than the standard drop shadow effect....
To get started, make another duplicate of our text layer by draging it down to the New Layer button in the Layers panel again. Rename this new layer as "Shadow".
Before we can go any further, you need to rasterize the Shadow layer. Change the Lightness of the layer by selecting Image » Adjustments » Hue / Saturation. Drop the Lightness down to -100 (Screenshot).
Fig. 6 |
Next, use the Distort tool (Edit » Transform » Distort) to bring the "shadow" layer to a little more than half of its original size, then stretch the top out just a little (not as much as we did on the reflection) (Screenshot). We're almost done...
Fig. 7 |
Reorder the layers so that the "shadow" layer is below the original text layer, but above the background. All that is left to do is to apply a Gaussian Blur (Filters »Blur » Guassian Blur) with a two or three pixel radius (Screenshot).
Fig. 8 |
That's all there is to it. I hope this comes in handy for you. And if it does, please let me know! I'd love to hear about it.
Sunday, July 8, 2007
I hear the train a comin'...
Over this past weekend, the family and I traveled to St. Louis, as we do about once every other month to visit Christina's family. Normally we'll drive the 7 hours from Little Rock to St. Louis, we've flown a couple of times, but this time we decided to try something different. The idea was actually inspired by my 4-year-old step-son who, as most toddlers do, has an infatuation with trains. Yes, we did; we took a train to St. Louis and back. I decided to describe the details of our adventure in transportation and provide some suggestions in between.
When we first considered the idea, it sounded novel. After a short trip across cyber-space we discovered that the cost was actually little more than we would otherwise spend on gas alone. The phrase, "It's something different", was spoken more times than I can remember as an explanation to our friends and family after we had purchased the tickets online. As I'm riding home now, I realize just exactly what "different" means.
Having never been on a train before I was expecting a train and station similar to those you see in the movies... I can guarantee you that the Little Rock Train Station will not be seen in Mission Impossible IV.
We arrived at the station in Little Rock at about 11 pm, as all passenger trains travel through the capitol city late at night. The high-backed wooden benches, tile floor and vaguely present air-conditioning of the station was reminiscent of an old southern church on a summer Sunday night (I expected a sweaty preacher to appear with a "hellfire and brimstone" sermon at any minute). Most of our fellow passengers seemed to have collaborated on matching luggage: Wal-Mart sacks and trash bags mostly. I think it really added something to the motif of the station. So much for first impressions.
I would make some kind comment about security, if there was any. Ok, all right, I'll take that back... I was asked for my ID... twice. Seriously though, it was as if we had entered a world where we were no longer at war. There wasn't a single semblance of any real security: no security guards, no TSA agents, there wasn't even a freaking metal detector for Pete's sake! Oh, that's ok Mr. Chertoff, I'm sure the enemies of the United States are only interested in hitting airborne targets, you can go back to sleep now.
As we boarded the train in Little Rock, we crept up into the second level of the car where we found our seats. Most of the people onboard were sleeping in all kinds of positions in their seats. Once we were settled in, we attempted to do the same. This became a futile effort.
Suggestion #1: Get a bed.
While the crew made a valiant effort to provide a comfortable atmosphere for those who wanted to sleep in their seats, you just can't get a good night's rest with an armrest between your cheeks (if you know what I mean). Upgrading your travel to include a bed is a little more costly, but it will be worth it in the end.
While the crew made a valiant effort to provide a comfortable atmosphere for those who wanted to sleep in their seats, you just can't get a good night's rest with an armrest between your cheeks (if you know what I mean). Upgrading your travel to include a bed is a little more costly, but it will be worth it in the end.
The next morning the conductor stopped by to make sure that we knew that the Dining Car was open for breakfast. Originally this wasn't part of our plan, but since the train was running about 90 minutes late (and we weren't quite ready to give up our adventurous spirit) we figured we'd give it a shot.
Suggestion #2: Get a bite.
The service and the food in the Dining Car were excellent. Breakfast being my favorite meal of the day, there's nothing better to start your day than a western omelet, toast, fresh fruit and hot cup of joe, all while enjoying some of America's scenic beauty.
The service and the food in the Dining Car were excellent. Breakfast being my favorite meal of the day, there's nothing better to start your day than a western omelet, toast, fresh fruit and hot cup of joe, all while enjoying some of America's scenic beauty.
Suggestion #3: Set a loose schedule
We arrived at the station in St. Louis almost two hours late. Luckily we were able to call ahead and let the rest of the family know not to drive 40 minutes out of their way just yet. Hindsight shows this to be a recurring theme in rail-travel with Amtrak, as our homeward-bound train picked us up over two hours past it's scheduled time and we arrived back in Little Rock a full three hours late.
We arrived at the station in St. Louis almost two hours late. Luckily we were able to call ahead and let the rest of the family know not to drive 40 minutes out of their way just yet. Hindsight shows this to be a recurring theme in rail-travel with Amtrak, as our homeward-bound train picked us up over two hours past it's scheduled time and we arrived back in Little Rock a full three hours late.
After trying to decide whether this was a good experience or bad, I think it's best said: this was a learning experience. Will we do it again? Maybe so... but we'll definitely get a Sleeper Car with beds... and a hot cup of joe in the morning.
Wednesday, March 14, 2007
Ajax made simple
Any article about Ajax should probably start by explaining that it's not a new programming language. Rather, it's a methodology that enables a greater level of user interactivity in web-based applications. Ajax is based on two languages that have been around for quite a while: JavaScript and eXtensible Markup Language (XML). The "A" in Ajax stands for asynchronous, which literally means, "not at the same time." This is the key that separates Ajax from the classic web page.
In your standard web application model, there is a "back and forth" kind of action. The user requests a web page, the page is served, and in order for the user to see any additional information, he/she must make a separate call for data for more data, which causes (at a minimum) the page to reload. Requests and responses for the new data set occur at the same time, or synchronously.
Using the Ajax methodology, you can add the same level of interactivity to your web-based applications that, previously, was unique to desktop applications. In this model, the user requests a web page and the page is loaded as normal. The difference is that each time the user needs to be presented with more data, a JavaScript makes a call back to the server and retrieves the data in an XML format. This allows the developer to change the content of the page without reloading the entire page. As you can imagine, this can be extremely appealing to the end user. Ok, so lets get started...
In order to fully understand this article, I have to assume that you already have a firm understand of HTML, JavaScript and XML. Teaching these components of Ajax is outside the scope of this article, but you can find some excellent tutorials at http://www.w3schools.org.
Now, let's describe what you are going to create. We are going to create two select boxes from which we can select a Make and Model of vehicle. The Models that we can select from will be determined by the Make that is first selected.
Aside from the HTML present, you'll need an XML file. If you don't have one handy, you can use the one from this example (20070314.xml). After you have an XML file, you'll need a JavaScript that you can call to load the XML document. For this you can copy the script below:
function ajaxRead(url, method, parameters, functionToRunWithXMLResponse) { var xmlObj = null; if (document.all) { xmlObj = new ActiveXObject("Msxml2.XMLHTTP"); } else { xmlObj = new XMLHttpRequest(); } xmlObj.onreadystatechange = function() { if(xmlObj.readyState == 4) { if (xmlObj.status == 200) { eval(functionToRunWithXMLResponse + "(xmlObj)"); } else { alert("The requested operation returned an error code: " + xmlObj.status + "\n\n" + xmlObj.statusText); return; } } } xmlObj.open (method, url, true); if (method == "POST") { xmlObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlObj.setRequestHeader("Content-length", parameters.length); xmlObj.setRequestHeader("Connection", "close"); } else { parameters = ""; // Just to make sure it was called correctly. } xmlObj.send (parameters); }
The ajaxRead function will access the given URL to read the XML file once it reads the XML file it then passes the XML Document Object to whatever function you specify in the functionToRunWithXMLResponse parameter. Here is an example of how the ajaxRead function should be called:
ajaxRead('/xml/cars.xml', 'GET', '', 'loadMakes');
Once you have the XML Document Object, you can simply crack open the XML document itself with JavaScript using the Document Object Model (DOM) and have your way with the data. In the example above I have chosen to simply load the names of the Makes and Models into a pair of select boxes.
function loadMakes(objXML) { // Get a handle on the XML Document Object passed from the ajaxRead function. var xmlDoc = objXML.responseXML.documentElement; var arrLevelOne = xmlDoc.childNodes; var intLength; //Populate the Makes for (var x = 0; x < arrLevelOne.length; x++) { intLength = document.form1.selectMake.options.length; document.form1.selectMake.options[intLength] = new Option(xmlDoc.childNodes(x).childNodes(0).text, xmlDoc.childNodes(x).childNodes(0).text); } document.form1.selectMake.options[0] = new Option("Select a Make", "Select a Make"); document.form1.selectMake.options.selectedIndex = 0; }
The last thing I did to complete the example given was create another JavaScript function that loaded the Models based on make that ran when the onChangeevent fired from the Make select box.
Using this method of web application development, developers can create fully interactive applications that enrich the user's experience and actually change the way your site's visitors think about the web.
Supporting documents:
Subscribe to:
Posts (Atom)