forked from weirdhome

Fork of HTTPClient by David Smart

Revision:
39:21fc7a4b6927
Child:
40:bcb19f8dbba3
diff -r 2ef07232f65c -r 21fc7a4b6927 data/HTTPiCal.h
--- /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