Fork HTTPClient and Modfiy code for mbed 6.0
Dependents: mbed-demo-http-get-json
Diff: data/HTTPiCal.h
- Revision:
- 39:21fc7a4b6927
- Child:
- 40:bcb19f8dbba3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/HTTPiCal.h Fri Mar 10 02:53:09 2017 +0000 @@ -0,0 +1,361 @@ +#ifndef HTTPICAL_H +#define HTTPICAL_H +#include <mbed.h> +#include "../IHTTPData.h" + + +/// An iCal handling mechanism - downloads and parses calendar events +class HTTPiCal : public IHTTPDataIn { + + public: + #define SUMMARY_CHARS 100 + #define LOCATION_CHARS 100 + #define CATEGORY_CHARS 20 + #define LINEBUFLEN 200 + + /// The repeat attribute for an event + typedef enum { + rptfNone, ///< no repeat for this event + rptfDaily, ///< daily repeat + rptfWeekly, ///< weekly repeat + rptfMonthly, ///< monthly repeat + rptfYearly ///< yearly repeat + } RepeatFreq_t; + + typedef int32_t tz_sec_t; + typedef int16_t tz_min_t; + + /// A single event consists of quite a number of attributes. + typedef struct { + time_t Start; + time_t End; + time_t Until; + uint16_t Count; + uint16_t Interval; + RepeatFreq_t RepeatFreq; + uint8_t RepeatDays; // bit mapped (bit 0 = sunday, bit 1=monday, ...) + uint16_t RepeatMonths; // bit mapped (bit 0 = jan, 1=feb, ...) + uint32_t RepeatMonthDay; // bit mapped (bit 1 = 1st, 2=2nd, ...) + uint32_t RepeatMonthDayRev; // reverse -1 = last day = bit 1, -2=bit 2, ... + char Summary[SUMMARY_CHARS]; + char Location[LOCATION_CHARS]; + char Category[CATEGORY_CHARS]; // "Green", ... + int Priority; // 1 == High, 5 == Normal, 9 == Low + } Event_T; + + + /// Instantiate HTTPiCal + /// + /// @code + /// HTTPClient http; + /// HTTPiCal iCal(10); // define a limit of 10 events to be held + /// + /// http.basicAuth(calInfo.user, calInfo.pass); + /// + /// time_t now = t.timelocal(); // Set a 4-hour window from now + /// time_t nxt = now + 4 * 3600; + /// ical.SetTimeWindow(now, nxt); + /// HTTPErrorCode = http.get(calInfo.url, &iCal); + /// if (HTTPErrorCode == HTTP_OK) { + /// // calendar successfully downloaded + /// for (int i=0; i<iCal.GetEventCount(); i++) { + /// HTTPiCal::Event_T event; + /// if (ical.GetEvent(i, &event)) { + /// printf("Event %d\r\n", i); + /// printf("Summary : %s\r\n", event.Summary); + /// printf("Location: %s\r\n", event.Location); + /// printf("Category: %s\r\n", event.Category); + /// } + /// } + /// } + /// @endcode + /// + /// @param count is the number of Event_T entries to reserve space for. + /// + HTTPiCal(int count); + + /// Destructor to free memory + ~HTTPiCal(); + + /// Set the time window of interest, for which to retain events. + /// + /// This sets the time window of interest. Any event, whether directly + /// scheduled in this window, or indirectly via repeat attributes, will + /// be retained in the list of available events. Any event not in this + /// window will be ignored. + /// + /// @param StartTime is the optional time value for the beginning of + /// interest. If gridStartTime is zero, no filtering is performed. + /// @param EndTime is the optional time value ending the period of interest. + /// + void SetTimeWindow(time_t StartTime = 0, time_t EndTime = 0); + + /// Get the count of Events currently available. + /// + /// @returns the count of events. + /// + int GetEventCount(void) { return EventCount; } + + /// Get a copy of the specified event. + /// + /// @param i is the event number, ranging from 0 to GetEventCount() + /// @param event is a pointer to where the event will be copied. + /// @returns true if the event was available and copied. + /// + bool GetEvent(unsigned int i, Event_T * event); + + protected: + + friend class HTTPClient; + + /** Reset stream to its beginning + * Called by the HTTPClient on each new request + */ + virtual void writeReset(); + + /** Write a piece of data transmitted by the server + * @param[in] buf Pointer to the buffer from which to copy the data + * @param[in] len Length of the buffer + * @returns number of bytes written. + */ + virtual int write(const char* buf, size_t len); + + /** Set MIME type + * @param[in] type Internet media type from Content-Type header + */ + virtual void setDataType(const char* type); + + /** Determine whether the data is chunked + * Recovered from Transfer-Encoding header + * @param[in] chunked indicates the transfer is chunked. + */ + virtual void setIsChunked(bool chunked); + + /** If the data is not chunked, set its size + * From Content-Length header + * @param[in] len defines the size of the non-chunked transfer. + */ + virtual void setDataLen(size_t len); + + private: + char lineBuf[LINEBUFLEN]; ///< workspace to copy [partial] lines into + + Event_T * EventList; ///< Pointer to the array of events + int EventSpaceCount; ///< Maximum number of events that can be tracked + int EventCount; ///< Current Count of events + + time_t gridStartTime; ///< defines the start of the time window of interest + time_t gridEndTime; ///< defines the end of the time winedow of interest + + int32_t tzoTZIDSec; + bool tzAdjusted; + + typedef enum { + idle, + inTimeZone, + inEvent + } seekstate_t; + seekstate_t seeking; + + #define min(a,b) (((a)<(b))?(a):(b)) + #define max(a,b) (((a)>(b))?(a):(b)) + + /// Determine if a specific timestamp is in a leap year + /// + /// @param[in] t is the timestamp to evaluate + /// @returns true if the specified timestamp is within a leap year + /// + bool isLeapYear(time_t t); + + /// Inspect the event to determine if its repeat attribute places it in the specified time window + /// + /// @param[in] start1 represents the start of the timerange of interest. + /// @param[in] end1 is the time range representing the end of the range of interest + /// @param[in] start2 is the time range of the event being tested + /// @param[in] end2 is the time range of the event being tested + /// @param[in] Event is a pointer to the event being tested and permits testing the repeat information. + /// @returns true if the event repeat pattern intersects with the display pattern + /// + bool RepeatMaskIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2, Event_T * Event); + + /// Convert 'n' characters in a string to an unsigned integer. + /// + /// @param[in] p is a pointer to the string. + /// @param[in] n is the number of characters to convert. + /// @returns an unsigned integer of the converted value. + /// + uint16_t AtoIxN(const char * p, int n); + + /// Parse some information from the stream and extract event information. + /// + /// @param[in] Event is a pointer to the current event to populate. + /// @param[in] pStart is a pointer to the start of a text stream to evaluate. + /// @param[in] tzoSec is the time zone offset in seconds. + /// + void ParseEvent(Event_T * Event, const char * pStart, tz_sec_t tzoSec); + + + /// Prepare to start processing an iCal stream + /// + /// This initializes the data structures for parsing. + /// + /// @code + /// ParseICalStart(); + /// while (receive(buf, ... )) + /// ParseICalStream(buf, ...); + /// count = ParseICalClose(); + /// @endcode + /// + void ParseICalStart(void); + + + /// End processing an iCal stream and return the number of events + /// + /// @returns number of events in range + /// + int ParseICalClose(void); + + + /// Parse an iCal stream, and extract everything useful. + /// + /// This accepts a pointer to a [large] buffer, which is the contents + /// of an iCal stream. It walked through all of the available + /// information to extract the Event list. + /// + /// @param[in] pStart is a pointer to the start of the stream. + /// @param[in] gridStartTime is a time value representing the start of the time-window of interest. + /// @param[in] gridEndTime is a time value representing the end of the time-window of interest. + /// @param[in] tzoMin is the time-zone offset in minutes. + /// @param[in] showEvents when true causes it to print the events as parsed. + /// @returns number of events in range. + /// + int ParseICalStream(const char * pStart, time_t gridStartTime, time_t gridEndTime, tz_min_t tzoMin, bool showEvents = true); + + + /// Get the number of events that have been cached. + /// + /// @returns the number of events. + /// + int GetNumEvents(void); + + /// Compute if the referenced event occurs within the specified time window. + /// + /// @param[in] startWindow is the starting timestamp. + /// @param[in] endWindow is the ending timestamp. + /// @param[in] Event is a pointer to the event, which can have repeat rules. + /// @returns true if the event laps into the current time window. + /// + bool EventIntersects(time_t startWindow, time_t endWindow, Event_T * Event); + + /// Compute the intersection of two time ranges, and evaluate the recurringing events. + /// + /// This compares a pair of time ranges, each by a start and end time. If they overlap + /// it then computes the intersection of those two ranges. Additionally, for a + /// specified Event, it will evaluate the recurring events that may also fall into + /// the target time range. + /// + /// @note This is usually the only API you need, as this will first call + /// the TimeIntersects function, and if that fails, then it will evaluate + /// repeat information. + /// + /// @param[in,out] start1 is the starting time of range 1. + /// @param[in,out] end1 is the ending time of range 1. + /// @param[in] start2 is the starting time of range 2. + /// @param[in] end2 is the ending time of range 2. + /// @param[in] Event is a pointer to the event of interest that may have recurring series. + /// @returns true if the ranges overlap, and then start1 and end1 are set to the + /// intersection. + /// + bool RepeatIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2, Event_T * Event = NULL); + + + /// Compute the intersection of two time ranges, and returns that intersection. + /// + /// This compares a pair of time ranges, each by a start and end time. If they overlap + /// it then computes the intersection of those two ranges. + /// + /// @param[in,out] start1 is the starting time of range 1. + /// @param[in,out] end1 is the ending time of range 1. + /// @param[in] start2 is the starting time of range 2. + /// @param[in] end2 is the ending time of range 2. + /// @returns true if the ranges overlap, and then start1 and end1 are set to the + /// intersection. + /// + bool TimeIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2); + + + // Private Functions - no real value external to the iCal public interface + // other than for test code. + + /// Computes the next interval for iCal events that have recurrence. + /// + /// @param[in] baseT is the base time value which is a factor only in leap-year. + /// @param[in] repeatFreq is a value representing the frequency of recurrence - + /// 0=none, 1=daily, 2=weekly, 3=monthly, 4=yearly + /// @param[in] interval is the multiplier of that repeat frequency to the next + /// event. + /// @returns a time_t value which is the incremental interval, and would be added + /// to a reference time. + /// + time_t NextInterval(time_t baseT, int repeatFreq, int interval); + + + /// Format a ctime value as a string, without the trailing <cr> + /// + /// This uses the normal ctime function, which appends a <cr>, but + /// it then removes that trailing line ending character. Additionally, + /// this keeps a few local static buffers to return the time string in + /// which permits a printf (for example) to call this api a few times + /// and get the proper representation of each. + /// + /// @param[in] t is a time value; + /// @returns a pointer to a static buffer containing the converted time. + /// + char * FormatCTime(time_t t); + + /// Sort the Events that have been extracted from the iCal results. + /// + void SortEvents(); + + /// Show the details for a specific Event, on the specified serial stream. + /// + /// Most useful during development, and perhaps no value after that. + /// + /// @param[in] Event is the event of interest. + /// + void ShowEventInfo(Event_T & Event); + + /// Access the 2-letter abbreviation for the day of the week. + /// + /// @param[in] i is the day of the week, where 0 = sunday + /// @returns a pointer to the 2-letter abbreviation. + /// + const char * RepeatDayAbbrev(int i); + + /// Parse a Datestamp string into a time value. + /// + /// Parses a string which can look like this: 20140505T200000 + /// into a time_t value. + /// + /// @param[in] string is the string to parse. + /// @param[in] tzoSec is the time-zone offset in seconds. + /// @returns time_t value. + /// + time_t ParseDateStamp(const char * string, tz_sec_t tzoSec); + + /// Parse a Time Zone ID value from the front-end of a Datestamp + /// + /// Parses a string which can look like one of these: + /// @li TZID="(GMT -06:00)":20140519T063000 + /// @li TZID:(UTC-06:00) Central Time (US & Canada) + /// @li TZID:(GMT -06:00) + /// + /// @param[in] string to be parsed. + /// @returns time zone offset in seconds. + /// + tz_sec_t ParseTZID(const char * string); + + + bool m_chunked; +}; +#endif // HTTPICAL_H \ No newline at end of file