Pages

Advertisement

Friday, August 10, 2007

Complex Loader

 

Although the simple loader may be all that you need, most large movies have something more elegant on the front end. Usually, there is a progress bar, as shown in figure

Figure 23.1. A progress bar, halfway through a load.

graphics/23fig01.gif

  1. Start a new movie.

  2. Draw a wide rectangle, complete with a border.

  3. Select the entire rectangle and turn it into a movie clip by choosing Insert, Convert to Movie Clip.

  4. Double-click on this new movie clip to edit it.

  5. Separate the rectangle's fill and border into two separate layers.

  6. Copy the rectangle fill and create a new layer to paste it into. This layer should have the border layer in front of it and the original rectangle behind it.

  7. Select the new rectangle and fill it a darker color. It should sit right on top of the lighter original rectangle.

  8. Now turn the darker rectangle into a movie clip by choosing Insert, Convert to Movie Clip. Give it any Library name you want, but give it the instance name bar in the Properties panel.

  9. Double-click on the dark rectangle movie clip to edit it. You'll need to reposition the rectangle so that the upper-left corner of the rectangle is at the movie clip's registration point (see Figure 23.2).

    Figure 23.2. The rectangle's upper-left corner is at the registration point.

    graphics/23fig02.gif

  10. Back in the main movie clip, create a fourth layer. Put a dynamic text field there. Link it to the variable displayText. Make it a nice big font, colored white.

  11. Go all the way back to the main timeline. Now we need to attach a script to the movie clip. It starts by setting up the bytesLoaded and bytesTotal variables.

    onClipEvent(load) {
    // initialize variables
    bytesLoaded = 0;
    bytesTotal = _root.getBytesTotal();
    }


  12. The enterFrame handler does most of the work. It monitors bytesLoaded and bytesTotal every frame. The variable percentLoaded is a value from 0 to 100. It is used in the text field but is also used to change the _xscale of the bar. Because the registration point is at the left, the left side of the bar stays in the same place, but the right side shrinks or grows according to _xscale.

    When the bytesLoaded equals bytesTotal, the display text is changed to a different message. The nextFrame command moves the movie forward to the next frame.



  13. The main timeline should be broken into three layers. The first layer has the loader bar movie clip that we have built. This stretches across the first two frames.



  14. Another layer has two separate key frames in frames 1 and 2. In frame 1 is a stop() command, but no other elements.



  15. The second frame of this new layer has a button. You can see it in Figure 23.3. The user clicks the simple button script to continue with the rest of the movie.

    Figure 23.3. The second frame of our loading movie allows the user to control when the rest of the movie begins.

    graphics/23fig03.gif

    on (release) {
    play();
    }


  16. The third layer of the movie contains the video—the large media piece that causes this movie to need a loading frame in the first place.

Wednesday, August 8, 2007

Stored Procedures for ASP, ASP.NET, VB and VB.NET Programmers


Requirements: Programming knowledge in ASP or VB, MS SQL server & Database concepts.

When I was starting my carrier as a VB programmer, All I knew for connecting a Database with my front-end are, the Data control and RDO. Later When I moved to ASP, I was enjoying writing SQL statements. It was fun when the SQL statements were simple and hard when it comes to complex and nested queries. Writing direct SQL commands inside my VB or ASP program were not been a big issue to me, until I started thinking about performance of my applications. But when time came, I started learning Stored Procedures I was really encouraged to do possible re-factoring of my previous coding with Stored Procedures, and my life with direct SQL commands came to an end. I hope my SP(Stored Procedure) history was not boring. With an assumption that you are good in ASP or VB and SQL let us begin SPs.

What are Stored Procedures?
SPs are an advanced feature in SQL server that offers you to create, compile and run SQL statements in the server itself, to isolate your business logic from data logic and to improve the performance of your application.
In short, write SQL queries in a specific format in the SQL server and call them from your application, instead of writing queries inside your program code.

Why write Stored procedures?

1.Mainly to increase the performance and the momentum to our programs. When you write a stored procedure, it will be pre-compiled by the SQL server, so that it can increase the speed of executing the queries and hence your application. When you write a stored procedure the database(DB) server automatically generates an execution plan for the procedure. The plan will be updated whenever a change is made in the procedure by the DB server.
2.You can take away all your SQL commands so that the data logic can be isolated from your business logic(ie.,Coding). This kind of encapsulation helps the web server to read and interpret lengthy and complex SQL commands.
3.Then like COM, stored procedures can be reused. For example if you want to do the same query in two different ASP pages or in VB forms, you can reuse the stored procedure which you have written for one page, It saves you time.
4.The application code as well as the stored procedure code are becoming easy to maintain. Updating a stored procedure may not affect the other part of an application or user who uses the same stored procedure.
5.The queries can be customized by using input/output parameters, like functions and procedures which you write in your programming languages.

What are the types of Stored Procedures?
There are three types of stored procedures. Microsoft supplies several stored procedures to manipulate and administrate the database. Apart from them can write custom stored procedure to use them in our application level.

1. System stored procedures:
System stored procedures are mainly used for administrating, assisting, configuring and monitoring the SQL server.
2. Extended stored procedures:
Extended stored procedures are used to access SQL server by using dlls. We can use C or C++ to write extended stored procedures with Dlls. One good example is accessing the operating system commands on SQL server. We can use a stored procedure called xp_cmdshell to to run a DOS command, like the following one.

xp_cmdshell "dir c:\",

will list the files in the root directory of C drive

3. Custom stored procedures:
These are the stored procedures we write. There are several advantages in writing our own stored procedures. We are able to write complex and nested statements with less effort.
In this article we focus only on custom stored procedures, in the following section.

Where to write Stored Procedures?
You can write Stored Procedures in the following possible ways,
1. Using SQL Server Enterprise manager - To create a stored procedure, Open SQL server enterprise manager,

  • Expand a server group; click and expand a server.
  • Expand Databases; select the database where under which you want to create the procedure.
  • Right-click Stored Procedures; then click New Stored Procedure..
  • Type the stored procedure. Press CTRL-TAB to indent the text of a stored procedure.
  • To check the syntax, click Check Syntax.
  • To set the permissions, click Permissions.

2. Using Query Analyzer - Open query analyzer, select the DB, type the procedure and execute it.
3. From ASP Code - Write the procedures, create the connection with the DB using ADO, call the procedures directly from your code.
4. Using Visual Studio.NET - VS.NET users can write their procedures using "create New Procedure" like in Enterprise Manager and check the syntax there itself.
5. Create using Enterprise manager wizard - We can also use the wizard to create the procedures. Follow the steps to use the wizard.

  • Expand a server group; then expand the server in which to create the view.
  • On the Tools menu click Wizards...
  • Expand Database.
  • Double-click Create Stored Procedure Wizard.
  • Complete the steps in the wizard.

Starting Stored Procedures
Now let us see an example procedure and peek into it a while for the basic understanding and structure of any stored procedure. I prefer enterprise manager to write stored procedure, and during the time of learning I recommend you to use Enterprise manager.

CREATE PROCEDURE sp_selauthors AS
BEGIN 
 
SELECT au_fname,au_lname,title,pub_name,pub_year
FROM tblAuthors 
WHERE pub_name = 'WROX'
 
END 
 
GO
 

After tying the procedure you can immediately check the syntax. Here all the SQL commands will be written in the BEGIN...END block. Here sp_selauthor is the procedures name.
All about parameters
We have seen a simple stored procedure that just selects the required values from a table. Now let us see a little more complex stored procedure with parameters. Stored procedures allow input and output(i/o) parameters to have a better control over the i/o values.
Here is an example with an input parameter,


CREATE PROCEDURE sp_selauthors 
@publisher_name varchar(50)
AS
BEGIN
 
SELECT au_fname,au_lname,title,pub_name,pub_year
FROM tblAuthors 
WHERE pub_name = @publisher_name
 
END
 
GO
 

....................[EXAMPLE1]

In the above example, @publisher_name is the input parameter and the values will be sent by your ASP or VB code. We will see, how to send values shortly.

Another example , an Insert statement, with two input parameter can help us to understand better.



CREATE PROCEDURE sp_InsName
@FirstName varchar(20), 
@LastName varchar(30)
AS 
BEGIN
INSERT INTO Names(FirstName, LastName)values(@FirstName, @LastName)
END
GO

....................[EXAMPLE2]
Here is an example with an output parameter,


CREATE PROCEDURE sp_sel_no_authors 
@count_authors int OUTPUT
AS
BEGIN
 
SELECT @count_authors = Count(*) FROM 
tblAuthors 
WHERE tblAuthors.pub_Name = "Wrox"
 
END
 
GO
 

....................[EXAMPLE3]

Here, the total no of authors who write for WROX press will be counted and sent through the output parameter. You can see the keyword OUTPUT to differentiate the output parameter from the input parameter.

Calling Stored procedures from your ASP code
Now let us call the stored procedure from ASP code. I will take stored procedure EXAMPLE2, to explain.



<%
   1: Dim objConn, sqlInsName, FName, LName
   2: FName = "Benny"
   3: LName = "Alexander"
   4: set objConn = Server.CreateObject("ADODB.Connection")
   5: objConn.Open "DSN=macdb;uid=test;pwd=test" 
   6: sqlInsName = "sp_InsName '" & FName & "', '" & LName & "'"
   7: objConn.Execute(sqlInsName) 
%>

The line ObjConn.Excecute runs the SP from the ASP code. Hope you understand how simple it is.
In the following ASP code we are going to see how to use command object to execute a stored procedure and also to get a OUTPUT value from the stored procedure.
Here I am using the stored procedure EXAMPLE3 for illustration.



<%
   1:  <!--#INCLUDE VIRTUAL="/include/adovbs.inc"-->
   2: Dim objConn, objCmd, objParam
   3: set objConn = Server.CreateObject("ADODB.Connection")
   4: objConn.Open "DSN=macdb;uid=test;pwd=test" 
   5: Set objCmd = Server.CreateObject("ADODB.Command")
   6: objCmd.CommandText = "sp_sel_no_authors"
   7: objCmd.CommandType = adCmdStoredProc
   8: objcmd.ActiveConnection = objConn 
   9: Set objParam = objCmd.CreateParameter ("@count_authors",adInteger,adParamOutput,4)
  10: objCmd.Parameters.Append objParam
  11: ObjCmd.Execute
  12: <HTML>
  13: <BODY>
  14: No of Authors write for wrox are: <%= objCmd.Parameters.("@count_authors")
%>
</BODY> 
</HTML> 

You may need a little explanation on the above written ASP code. Here I create a command object objCmd, and setting the parameters. The name of the returned variable is "@count_authors", which is also mentioned in the stored procedure. The type of this variable is integer with length 4. When I execute the SP, sp_sel_no_authors, I get the return value, as output which can be displayed in the web page. I hope this two examples are sufficient enough for ASP programmers. Now let us turn to VB.

A Tip: You may get an error when you pass date as an input parameter. In that case send the date as a string and convert the string as date inside the SP.
For example if you pass the date as a variable called Orderdate, Then add the following lines of code in your stored procedure,



DECLARE @Orderdate DATETIME
SELECT @Orderdate=CONVERT(datetime, @Orderdate)

Here we convert the date string into datatime data type. In this way you can manipulate dates.

Calling Stored procedures from your VB code
If a stored procedures that do not return records (or rows) can be executed from Visual Basic with the ExecuteSQL() method as follows. That means we can not use this method with SELECT statements. But if the the SQL statement returns records then we need to use a Dynaset or Snapshot to capture the values. The following returns a set of recordset values using a Data control.




objDC.Options = dbSQLPassThrough
objDC.Recordsource = "sp_sel_no_authors" 
objDC.Refresh

Another example can give you better understanding with stored procedures that return values and that not return values.




Dim objDB as Database
Dim lng as Long
Dim objRS as Recordset
Set objDB = DBEngine.Workspaces(0).OpenDatabase("", False, False,"ODBC;_ DSN = macdsn;uid=test;pwd=test:") ' For SPs that don't return rows.
lng = Db.ExecuteSQL("YourSP_Name") ' SP which return rows.
Set ObjRS = Db.OpenRecordset("YourSP_Name", dbOpenSnapshot, _
dbSQLPassThrough)
Column1.text = objRS(0) ' Column one
Column2.text = objRS!ColumnName ' Column two
Column3.text = objRS("ColumnName") ' Column three

Handling errors in stored procedures
In this section we will cover the necessary information you need to know about finding and dealing errors in a stored procedure during the time of execution. In fact there are about 3800 SQL server error messages, which are maintained in the master catalog's "sysmessages" table. Every error message has its own severity level and it ranges from 0 to 25, depending on how bad the error is.
There are two types of errors you can face when you execute a stored procedure in a SQL server. One is Fatal and another one is nonfatal. Fatal errors normally terminates the execution of the SP and terminates the connection between the SQL server and the client application while nonfatal errors do not.
Here is an example for Fatal error, I am trying to execute a SELECT SQL statement in a table which does not exist.



CREATE PROCEDURE sp_Fatal
SELECT * FROM empDB
PRINT 'Table Does not exist.' 
GO 

As this table doesn't exist the SQL server raises a Fatal Error and the execution of the procedure terminates. So the PRINT statement will not be executed and we will not get the error message 'Table Does not exist'. Instead we get the error message raised by the Server.
Server: Msg 208,Level 16,State 1,Procedure sp_Fatal,Line 3 Invalid object name 'empDB'.

With one example the nonfatal errors can be illustrated. Let us assume that you are trying to Insert NULL value to a filed which is designed a Primary key. This will raise a non fatal error and will allow you to execute the entire procedure.

In three ways you can get the catch the errors in Stored procedures. Using @@ERROR, SP_ADDMESSAGE, and RAISERROR functions within SQL the Server. Let us discuss the one by one.
@@ Error method:
The @@ERROR system function returns 0 if the last procedure executed successfully; if the statement generated an error, @@ERROR returns the error number. The following example explains with an Insert statement,


CREATE PROCEDURE sp_addEmployee
@empId varchar(10),@empName varchar(40),@phone char(12),@address varchar(40) = NULL,
@city varchar(20) = NULL,@state char(2) = NULL,@zip char(5) = NULL
AS
 
INSERT INTO tblEmployee
(fldEmpId, fldEmpName, fldPhone, fldAddress, fldCity, fldState, fldZip) values(@au_id,@au_lname,@au_fname,@phone,@address,@city,@state,@zip,@contract)
 
IF @@ERROR <> 0 
 
BEGIN
PRINT "An error occurred while adding the new Employee information"
RETURN(99)
END
 
ELSE
 
BEGIN
PRINT "The new author information has been loaded"
RETURN(0)
END
 
GO
 

In this example the IF...ELSE statements test @@ERROR after an INSERT statement which inserts the employee details in a stored procedure. The value of the @@ERROR variable determines the return code sent to the calling program, indicating the success or failure of the procedure.
Using SP_ADDMESSAGE :
SP_ADDMESSAGE is a system stored procedure used to add a new error message to the sysmessages table. This message could be a custom defined one. The syntax for this stored procedure is,



sp_addmessage [@msgnum =] msg_id, 
[@severity =] severity, 
[@msgtext =] 'msg' 
[, [@lang =] 'language'] 
[, [@with_log =] 'with_log']
[, [@replace =] 'replace']

Here, [@msgnum =] msg_id is the ID of the message; [@severity =] is the severity level of the error (severity is smallint) and value varies from 0-25 as mentioned earlier; [@msgtext =] 'msg' is the text of the error message; [@lang =] 'language' is the language for this message, which helps to display the error message in multiple languages. [@with_log =] is whether the message is to be written to the Microsoft® Windows NT® application log when it occurs, the value will be true or false. [@replace =],If specified as the string REPLACE, an existing error message is overwritten with new message text and severity level.
An example which adds a new error message is,



EXEC sp_addmessage 50001, 16, 
N'Give perscentage value betwwn 1 to 10
Please reexecute with a more appropriate value.'

The RAISERROR method:
Though you can use print statements, RAISERROR is a more powerful statement than PRINT, for returning messages back to applications. In two ways RAISERROR can return messages.
1. Using sp_addmessage a user-defined error message has been added to master.dbo.sysmessages.
2. Using the message string specified in the RAISERROR statement.
The advantages of using RAISERROR over PRINT is it can assign a specific error number, severity, and state. Moreover the error can be logged.

The syntax for RAISERROR method is as follows,



RAISERROR ({msg_id | msg_str}, severity, state
[, argument1 [, argument2]])
[WITH options]


Stored Procedures for ASP, ASP.NET, VB and VB.NET Programmers

Tuesday, August 7, 2007

Flashing Stock Alert Application using C# and the Basic Stamp II

 

Flashing Stock Alert Application using C# and the Basic Stamp II
By  Mike Gold September 15, 2006

This article describes an application for reading stock quotes into an excel spread sheet and alerting the user when the stock quotes have exceeded or dropped below a certain price threshold. The project uses the SerialPort class to send commands to the Parallax Basic Stamp Microcontroller.

 

Figure 1 - Flashing Stock Alert using the Basic Stamp II and .NET

Introduction

In the stock market, a stock price can go for or against you at any time.  Traders need to be wary of price changes so that they don't lose a lot of money.  One method of warning the trader about price fluctuations is a flashing alert on the screen.  However, let's say for argument's sake that the trader is not at his or her computer.  What if the trader is across the room behind the computer screen?   How will he or she know that the alert has been tripped?  One way to show an alert is to sound an alarm from the PC and turn up the volume on the sound card.  On the other hand, this technique may piss off all the other traders (and you don't want to piss off a trader).  Another idea is to extend the visible signal of the stock alert beyond the computer screen.  Thus we have created the flashing stock alert.

Design

The flashing stock alert consists of two components:  

(1) The .NET solution that allows traders to set alerts in their favorite PC program-Microsoft Excel.  (2) The Parallax Basic Stamp II Circuit containing the Light Emitting Diode (LED) flashers used to alert the user. Here is how the application works: The trader types in the symbols of the stocks s/he wishes to monitor in the stocks column of the excel spreadsheet.  The prices of these stocks are then brought into the price column from a website that provides quotes and is updated every second.  The quote is also checked against a high and low value in the columns adjacent to the price column provided by the trader.  If the price exceeds the high value column or falls below the low value column a signal is sent over the serial port to the BASIC Stamp Board to alert the trader with a flashing LED.

Figure 2 - Block Diagram of System Design for Flashing Stock Alert

Working with an Office Project

The .NET code utilizes the Office Project capability in Visual Studio 2005.  If you click New -->Project and choose Office,  you can actually create a ready-made Excel project in which you can enter C# code to interact with an Excel spreadsheet.  Pretty cool, huh?  Now you can do all your coding for Excel in C# class files representing each of the different components of the COM model (i.e. sheets and workbooks).  You still have to deal with the old Excel object structure, but it beats coding for Excel through VBA.  You can even drop .NET components right onto the Excel SpreadSheet!   For example, you can drag a Button from the Visual Studio onto the Excel spreadsheet in your project and hook an event handler to it. (That feature pretty much blew me away when I tried it.)

Figure 3 - Utilizing the Office Project Capability in Visual Studio 2005

The .NET Code

When talking to Excel from .NET you need to work with Ranges.  Ranges can be any set of cells within the Excel Spread Sheet defined by the corners of the range (e.g. A1, B6).  Programming .NET to manipulate Excel is not as forgiving as one would expect because you are still going through the painful COM layer.  However, once you get the hang of it, you'll soon be populating and reading cells in Excel with C# code. 

The application design on the .NET side centers around three main classes: the Worksheet we are working in, a stock scraper for getting stock values from the web, and a serial port alert class that handles all the nitty gritty details of sending alerts to the Basic Stamp through the serial port.  The program works on a 1-second thread timer contained in the work sheet.  Every second, the timer event is triggered and PopulateStockPrice is called to populate the current stock prices of all the available symbols contained column A.   PopulateStockPrice also tests the high and low thresholds contained in columns C and D and sets off the alert if the price is outside the bounds of the constraints. 


Figure 4 - UML Design illustrating the 3 classes for our stock Alert Program

Let's examine the PopulateStockPrice method in the Sheet1 class code in Listing 1 since this is where all the action takes place.  The first thing we do is to get a list of stock symbols from the spread sheet in column A using the Range object in the excel sheet.  Then we loop through each of these symbols and scrape the current price of the stock off a website using the StockScraper.  Finally, we get the high and low constraints for the current symbol and test them against the current price using the SerialPortAlertSignal class.  If they are outside the bounds of the constraints, we send a signal to through the serial port to the Basic Stamp.

Listing 1 - Populating Stock Prices in Excel and Checking Them Against Constraints

private void PopulateStockPrices()
{
// get a list of all the symbols in column A
object[,] values = (object[,])this.Range["A2", "A50"].Value2;

// start in the second row, below the title row
int rowcount = 2;

// loop through all the symbols in column A
foreach (string symbol in values)
  {
// if we reached a blank symbol, then we reached
   // the end of the symbol list, break

    if (symbol == null || symbol.Length == 0)
   break;

// use the stock scraper to get the stock value
 // for the current symbol

   string val = _scraper.GetStockValue(symbol);

// set column B to the price received from the web
   this.Cells[rowcount, 2] = val;

// get the high price value constraint from column C
  string high = GetHigh(rowcount);

// test the high value against the current price
// and signal an alert if its outside the constraint

  _alertSignal.TestHigh(val, high);

// get the low price value from column D

  string low = GetLow(rowcount);

// test the low value against the current price
// and signal an alert if its outside the constraint

    _alertSignal.TestLow(val, low);

// go to the next row

    rowcount++;
  }
}

Screen Scraping Quotes:

There are many ways to get stock information from the internet.  The best way to get the most current quotes (real-time) is directly from a paid service such as Reuters.  Unfortunately, these services tend to be expensive.  For the purpose of this article, we scrape the screen of a web site that displays quotes.  The problem with screen scraping is threefold:  (1) quotes tend to be delayed as much as 15 minutes and not real-time.  (2) it's not necessarily the quickest way to retrieve a quote because you have to parse through an entire web page  (3)   you have no control over the content of the page, so if the page structure changes,  your screen scraper may not work anymore.  The nice thing about screen scraping quotes, however, is that it is free and good for demonstration purposes.  Below is the method that allows us to scrape a quote using our  StockScraper class shown in listing 2.  Basically, this method goes to the server URL providing the quote and extracts the web page into a string.  Then we scrape through the page looking for the quote based on known tags that point to the quote.  Remember that you have no control over these tags and they can change at any time.  If they do change, simply rewrite the GetStockValue method.

Listing 2 - The GetStockValue method in the ScreenScraper class

public string GetStockValue(string stock)
{

//Create a HttpWebRequest object for the server search URL
HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create(String.Format("{0}{1}&d=e", ServerURL, stock));

// retrieve the response web page we want to scrape and put it into a string
HttpWebResponse webresp = (HttpWebResponse)webreq.GetResponse();

StreamReader strm = new StreamReader(webresp.GetResponseStream(), Encoding.ASCII);
string res = strm.ReadToEnd();

// find  the price of the stock on the page by searching for it
// through a combination of known tags and the stock symbol

string quotePrefix = "<big><b>";
int quoteIndex = res.IndexOf(quotePrefix, res.IndexOf(String.Format("({0})", stock), res.IndexOf("setPortfolioBehavior()")));
quoteIndex += quotePrefix.Length;
string result = res.Substring(quoteIndex, 15);

// match the stock price using a regular expression for the
// numeric form #######.#######

Regex expression = new Regex(@"[0-9]+\.[0-9]+");
Match match = expression.Match(result);
result = result.Substring(match.Index, match.Length);

return result;

}

Sending Alerts over the Serial Port

Now we come to the fun part: talking to the hardware to alert the trader that the stock has tripped a boundary condition.  We can use our SerialPortAlertSignal class to communicate through the serial port to the board.  The serial port uses a protocol known as RS232 to communicate data sent back and forth through the port.  When we construct the SerialPortAlertSignal object, we take the opportunity to initialize our serial port settings.  Listing 3 shows the Initialize method of the SerialPortAlertSignal class.  For our purposes we set up the communication to be 9600 baud (9600 bits/sec) , 8 bits of data, 1 stop bit and no parirty.  The 8 bits of data indicate that each frame of data we send out will contain 8 bits of information. The stop bit tells the serial port chip when the data in that frame has completed.  Parity is used to check errors in the data, but we don't use it here.

Listing 3 - Setting up the Serial Port for (9600, 8, 1, n) baud communication at

/// <summary>

/// Data will be sent out on COM1: (9600, 8, 1, N)
/// </summary>
private void Initialize()
{
// set the com port we are using from the PC
 _serialPort.PortName = "COM1";

// set the baud rate (the rate that data is sent and received in bits/sec)
_serialPort.BaudRate = 9600;

// parity bit for error detection purposes: even, odd, or none
_serialPort.Parity = Parity.None;

// set stop bit to one (used to separate the data into frames)
_serialPort.StopBits = StopBits.One;

// set number of bits in each frame of data
_serialPort.DataBits = 8;

// no handshaking used
_serialPort.Handshake = Handshake.None;
}

The TestHigh and TestLow methods of the SerialPortAlertSignal class determine if we tripped our constraints in the high and low price range respectively.  If either of these methods tests true, we internally call the SetAlert command to send a character through the serial port to tell the Basic Stamp which LED to light:

Listing 4 - Testing stock prices to determine if we light the LED Alerts

public void TestHigh(string stockVal, string high)
 {
// convert the string price values to doubles
double val = Convert.ToDouble(stockVal);
double highVal = Convert.ToDouble(high);

// test if our price is higher than the constraint
if (val > highVal) 
     {
// set green for prices below threshold
         SetAlert("G");
      }
}

public void TestLow(string stockVal, string low)
{
   // convert the string price values to doubles
   double val = Convert.ToDouble(stockVal);
double lowVal = Convert.ToDouble(low);
// test if our price is lower than the constraint
   if (val < lowVal)
   {
     // set red for prices below threshold
    SetAlert("R");
   }
}

The SetAlert method of the SerialPortAlertSignal class talks directly to the serial port through the System.IO.Ports.SerialPort class which is part of the .NET framework.  This class makes it quite easy to both send and receive data via RS232 communication over a serial port on a PC.  (If your computer only has USB, you may need to get a serial port adapter to do this experiment).  SetAlert takes advantage of the Write method in the SerialPort class to write a string out onto the serial port. 

Listing 5 - Setting Alerts through the Serial Port to the Basic Stamp

public void SetAlert(string r)
{
// open the serial comm port
  _serialPort.Open();

// send the string over the serial port
_serialPort.Write(r);

// close the serial comm port
_serialPort.Close();
}

In our design, we use a character to indicate which LED we are lighting.  "R" indicates that we want to light the red LED and "G" indicates that we want to light the Green LED.  A character byte sent over the line is a binary representation in the form of a series of high and low signals.  For example "G", which is ASCII 71 (or hex 0x47)  would be represented as 01000111 and the signal would look like figure 5 over the serial port.  Note that the low horizontal segments are binary 0 and the high horizontal segments are binary 1.  These segments correspond to high and low voltages on the pins of the serial port.

Figure 5 - Logic High-Low Diagram Illustrating the ASCII "G" character sent over the RS232 serial port

The Basic Stamp

Parallax provides a microcontroller kit called the Board of Education (BOE) which allows you to easily control the Basic Stamp II microcontroller using the BASIC language. This kit fits our hardware requirements for this project.  The circuit shown in figure 6 connects our LEDs to three of the BASIC Stamps ports so that we can control their state by sending signals to the serial port.  220 ohm resistors are added in between the port and the LED to limit current going through the LED (so we don't burn them up).  We will take advantage of two features of the Basic Stamp to create our stock alerts. The first feature is the ability to receive command on the serial port and the second feature is the ability to toggle the logic state of ports 1,3 and 15 to light or extinguish the LEDs.

Figure 6 - Stock Alert Circuit hook up on the Board of Education

The code needed to program the Basic Stamp is shown in listing 6.  The SERIN command waits for the data from the serial port and when it receives the data, it places it in the command variable.  The Select statement chooses the appropriate subroutine to call based on the command received.  Based on the command, the appropriate port will be set either high or low to light or extinguish the LED.

The Basic Stamp language has a command called TOGGLE that allows you to toggle the state of the port.  If your previous state is high on the port, then TOGGLE sets the state to low and if the previous state is low on the port, then TOGGLE sets the state to high.  The TOGGLE command, which is called once every second, gives us the visual effect of a flashing LED.

Listing 6 - Basic Stamp II BASIC Code for Receiving Commands on the Serial Port and Lighting LEDs

Conclusion

As embedded system hardware becomes more accessible to the developer, more and more applications will take advantage of its powerful reach to the outside world. Connecting the Parallex BOE to your PC is an easy and fun way to implement hardware from your C# programs.  Although Microsoft provides a Robotics SDK to do some hardware control in Visual Studio, it's easy enough to get started without it. Simply plug the BOE board into the PC through the serial port and start coding.  Stay tuned for more practical applications with C#, .NET and the Board of Education from Parallax.

Suggestions:  A fun way to extend this project, would be to adapt it to the pocket PC.  Perhaps we will publish an adaptation in the near future.

 

Download the source file from Here