📄 wx.c
字号:
/********************************************************************* FILE: Wx.c** DESCRIPTION: UI for the weather station** VERSION: 1.0**********************************************************************/#include <PalmOS.h>#include <PalmCompatibility.h>#include <INetMgr.h>#include "Wx.h"#include "WxRsc.h"#include "Utils.h"#include "TinyTrig.h"#include "UtilsRsc.h"#include "nAPI.h"// Widget constantsconst RectangleType therColRect = { 12, 24, 6, 80 };const PointType therColBasePoint = { 12, 105 };const Coord therColBaseWidth = 6;const Coord therColBaseHeight = 80;const PointType windComBasePoint = { 81, 40 };const Coord windComWidth = 50;const Coord windComHeight = 50;const PointType windComCenterPoint = { 106, 65 };const double windComRadius = 24.0;// Incoming data format is:// Station name// Date m:d:y// Time h:m:// Wind speed in MPH// Wind direction in degrees// Temperature in degrees Farenheight// Humidity (percent)// Barometer in mB -- tenths// Rainfail last hour -- tenths// Rainfall last day -- tenthsconst Char *wxSampleInputString = "KF6GPE:3:22:2000:14:26:3:272:69:28:10277:0:2:";//const Char *wxURL = "http://www.lothlorien.com/~dove/wx.html";const Char *wxURL = "http://abacus.lothlorien.com/wx.vii";const Char *wxRecSep = ":";const UInt32 wxInputStringLen = 16384;typedef struct _WxInfoType{ Char name[32]; UInt32 time; Int32 windSpeed; Int32 windDir; Int32 temperature; Int32 barometer; Int32 humidity; Int32 rainHour; Int32 rainDay; Boolean init;} WxInfoType, *WxInfoTypePtr;typedef struct _WxLabelType{ Char windLabel[32], tempLabel[32], humLabel[32], baraLabel[32], precipLabel[32],timeLabel[32];} WxLabelType, *WxLabelTypePtr;static WxInfoType gWxData = { 0 };static WxLabelType gWxDisplay = { 0 };// static prototypes...void PatchKCS( void );void RemovePatchKCS ( void );/*********************************************************************** * FUNCTION: MainFormParseWxString * * DESCRIPTION: This routine parses the given weather string and * Updates the globals if the parse succeeds. * * RETURNED: error code or noErr for no error. ***********************************************************************/ static Err MainFormParseWxString // (out) error code on failure( const Char *wxP // (in) Current weather ){ Err anErr = dmErrNotValidRecord; Char temp[32]; Char *fieldStart, *fieldEnd; WxInfoType data = { 0 }; DateTimeType date = { 0 }; // Fetch the name. fieldStart = (Char *)wxP; fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( data.name, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); fieldStart = fieldEnd+1;// Fetch the date. month, day, year fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( temp, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); temp[ (fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ] = '\000'; fieldStart = fieldEnd+1; date.month = (short)StrAToI( temp ); fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( temp, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); temp[ (fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ] = '\000'; fieldStart = fieldEnd+1; date.day = (short)StrAToI( temp ); fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( temp, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); temp[ (fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ] = '\000'; fieldStart = fieldEnd+1; date.year = (short)StrAToI( temp );// now hours and minutes. fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( temp, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); temp[ (fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ] = '\000'; fieldStart = fieldEnd+1; date.hour = (short)StrAToI( temp ); fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( temp, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); temp[ (fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ] = '\000'; fieldStart = fieldEnd+1; date.minute = (short)StrAToI( temp ); data.time = TimDateTimeToSeconds ( &date ); // Wind speed and wind direction fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( temp, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); temp[ (fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ] = '\000'; fieldStart = fieldEnd+1; data.windSpeed = StrAToI( temp ); fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( temp, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); temp[ (fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ] = '\000'; fieldStart = fieldEnd+1; data.windDir = StrAToI( temp ); // temperature, humidity, and barometer fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( temp, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); temp[ (fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ] = '\000'; fieldStart = fieldEnd+1; data.temperature = StrAToI( temp ); fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( temp, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); temp[ (fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ] = '\000'; fieldStart = fieldEnd+1; data.humidity = StrAToI( temp ); fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( temp, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); temp[ (fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ] = '\000'; fieldStart = fieldEnd+1; data.barometer = StrAToI( temp );// Precipitation fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( temp, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); temp[ (fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ] = '\000'; fieldStart = fieldEnd+1; data.rainHour = StrAToI( temp ); fieldEnd = StrStr( fieldStart, wxRecSep ); if ( fieldEnd == NULL ) return anErr; StrNCopy( temp, fieldStart, (short)(fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ); temp[ (fieldEnd-fieldStart > 31 ? 31 : fieldEnd-fieldStart ) ] = '\000'; fieldStart = fieldEnd+1; data.rainDay = StrAToI( temp );// If we made it this far, assume the data's OK. anErr = noErr; gWxData = data; gWxData.init = true; return anErr;} /*********************************************************************** * FUNCTION: MainFormInit * * DESCRIPTION: This routine initializes the MainForm form. * * RETURNED: nothing ***********************************************************************/ static void MainFormInit( FormPtr frmP // Pointer to the MainForm form.){ if ( frmP != NULL ) { }}/*********************************************************************** * FUNCTION: MainFormDrawWind * * DESCRIPTION: This routine draws the wind compass * * RETURNED: nothing ***********************************************************************/static void MainFormDrawWind( void){ RectangleType windSourceRect = { 0, 0, windComWidth, windComHeight }; MemHandle bitmapH; BitmapType *bitmapP; if ( gWxData.init && gWxData.windSpeed > 0) { // Erase old one. bitmapH = DmGetResource( bitmapRsc, WindBitmap ); if ( bitmapH ) { bitmapP = MemHandleLock( bitmapH ); WinDrawBitmap ( bitmapP, windComBasePoint.x, windComBasePoint.y ); MemHandleUnlock( bitmapH ); DmReleaseResource( bitmapH ); // Calculate where the line indicating wind direction needs to go. // Wind direction is in degrees with 0 being north. // We need to add 90 degrees, convert to radians first. // Then we calculate the point on the wind compass using the circle // equation r * cos theta, r *sin theta. { double angleDeg, angleRad; Coord x1, y1, x2, y2; double cx, cy; angleDeg = (double) gWxData.windDir - 90.0; angleRad = angleDeg/360 * ( TWO_PI ); cx = _cos( angleRad ); cy = _sin( angleRad ); x1 = windComCenterPoint.x; y1 = windComCenterPoint.y; x2 = (Coord)( windComRadius * cx ) + x1; y2 = (Coord)( windComRadius * cy ) + y1; WinDrawLine ( x1, y1, x2, y2); } } else { // Dang. Who was messing with the sources here?? } }}/*********************************************************************** * FUNCTION: MainFormTemp * * DESCRIPTION: This routine draws the gWxData.temperatureerature column. * * RETURNED: nothing ***********************************************************************/static void MainFormDrawTemp( void){ RectangleType column; Coord height; RectangleType windSourceRect = { 0, 0, windComWidth, windComHeight }; MemHandle bitmapH; BitmapType *bitmapP; if ( gWxData.init ) { bitmapH = DmGetResource( bitmapRsc, ThermometerBitmap ); if ( bitmapH ) { bitmapP = MemHandleLock( bitmapH ); WinDrawBitmap ( bitmapP, 5, 15 ); MemHandleUnlock( bitmapH ); DmReleaseResource( bitmapH ); } WinEraseRectangle ( &therColRect, 0 ); height = (short)((float)( gWxData.temperature - 20 ) * (float)(4.0 / 5.0)); // bound check! height = height < 0 ? 0 : height; height = height > therColBaseHeight ? therColBaseHeight : height; column.topLeft.x = therColBasePoint.x; column.topLeft.y = therColBasePoint.y - height ; column.extent.x = therColBaseWidth; column.extent.y = height; WinDrawRectangle ( &column, 0 ); }}/*********************************************************************** * FUNCTION: MainFormDrawTime * * DESCRIPTION: This routine draws the gWxData.temperatureerature column. * * RETURNED: nothing ***********************************************************************/static void MainFormDrawTime( void){ DateTimeType date; char *timeP; if ( gWxData.init ) {// Draw Last reading date and time TimSecondsToDateTime ( gWxData.time, &date ); DateToAscii ( (UInt8)date.month, (UInt8)date.day, (UInt16)date.year, dfMDYWithSlashes, gWxDisplay.timeLabel ); timeP = gWxDisplay.timeLabel + StrLen( gWxDisplay.timeLabel ); *timeP = ' '; TimeToAscii ( (UInt8)date.hour, (UInt8)date.minute, tfColon24h, timeP + 1); WinDrawChars( gWxDisplay.timeLabel, StrLen( gWxDisplay.timeLabel ), 45, 2 ); }}/*********************************************************************** * FUNCTION: MainFormDraw * * DESCRIPTION: This routine draws the non-form contents of the MainForm form. * * RETURNED: nothing ***********************************************************************/ static void MainFormDraw( FormPtr frmP // Pointer to the MainForm form.){ if ( frmP != NULL ) { // Insert code as appropriate MainFormDrawTemp ( ); MainFormDrawWind ( ); MainFormDrawTime ( ); }}/*********************************************************************** * FUNCTION: MainFormUpdate * * DESCRIPTION: This routine updates the fields of the form and posts * a redraw request. * * RETURNED: nothing ***********************************************************************/ static void MainFormUpdate( FormPtr frmP){ FrmEraseForm( frmP ); // Form title -- the station name. FrmSetTitle ( frmP, gWxData.name ); // Wind StrPrintF ( gWxDisplay.windLabel, "%ld mph from %ld \260", gWxData.windSpeed, gWxData.windDir ); CtlSetLabel ( GetObjectPtr ( MainWindLabel ), gWxDisplay.windLabel ); // Temperature StrPrintF ( gWxDisplay.tempLabel, "%ld \260F", gWxData.temperature ); CtlSetLabel ( GetObjectPtr ( MainTempLabel ), gWxDisplay.tempLabel ); // Humidity StrPrintF ( gWxDisplay.humLabel, "%ld%%", gWxData.humidity ); CtlSetLabel ( GetObjectPtr ( MainHumidityLabel ), gWxDisplay.humLabel ); // Barometer StrPrintF ( gWxDisplay.baraLabel, "%4ld.%1ld mB", gWxData.barometer / 10, gWxData.barometer % 10 ); CtlSetLabel ( GetObjectPtr ( MainBarometerLabel ), gWxDisplay.baraLabel ); // Precipitation StrPrintF ( gWxDisplay.precipLabel, "%ld.%1ld in/hour %ld.%1ld in/day",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -