/// <summary> /// Parse data entries in CSV format /// </summary> /// <param name="data">Data entries in CSV format</param> /// <returns>List of all data entries</returns> public static ArrayList ParseCsv(string data) { ArrayList dataEntries = new ArrayList(); int i = 0; // split response lines on line feed string[] lines = data.Split(LF); // extract column headers string[] headers = lines[i++].Split(','); while (i < lines.Length) { // extract token on current line string[] tokens = lines[i].Split(','); DataEntry dataEntry = new DataEntry(); // parse all tokens for (int j = 0; j < tokens.Length; j++) { // date/time if (headers[j] == "created_at") { // date/time in UTC format dataEntry.DateTime = DataEntry.Parse(tokens[j]); } // entry id else if (headers[j] == "entry_id") { dataEntry.Id = Convert.ToInt32(tokens[j]); } // any field (field1, field2, .... field8) else if (headers[j].Substring(0, 5) == "field") { int fieldIdx = Convert.ToInt32(headers[j].Substring(5, 1)); dataEntry.Fields[fieldIdx - 1] = tokens[j]; } // latitude else if (headers[j] == "latitude") { if (tokens[j] != String.Empty) { if (dataEntry.Location == null) dataEntry.Location = new Location(); dataEntry.Location.Latitude = Convert.ToDouble(tokens[j]); } } // longitude else if (headers[j] == "longitude") { if (tokens[j] != String.Empty) { if (dataEntry.Location == null) dataEntry.Location = new Location(); dataEntry.Location.Longitude = Convert.ToDouble(tokens[j]); } } // elevation else if (headers[j] == "elevation") { if (tokens[j] != String.Empty) { if (dataEntry.Location == null) dataEntry.Location = new Location(); dataEntry.Location.Elevation = Convert.ToDouble(tokens[j]); } } else if (headers[j] == "location") { // TODO } // status else if (headers[j] == "status") { if (tokens[j] != String.Empty) dataEntry.Status = tokens[j]; } } dataEntries.Add(dataEntry); i++; } return dataEntries; }
/// <summary> /// Update a channel /// </summary> /// <param name="writeApiKey">Write API Key for the channel to update</param> /// <param name="dataEntry">Data entry for updating channel</param> /// <returns>Update result</returns> public bool Update( string writeApiKey, DataEntry dataEntry) { // check for a mandatory write API Key if ((writeApiKey == null) || (writeApiKey == String.Empty)) { throw new ArgumentNullException("writeApiKey", "You must specify a write API Key"); } // check max fields number if (dataEntry.Fields.Length > THING_SPEAK_MAX_FIELDS) { throw new ArgumentException("fields", "Max number of field is " + THING_SPEAK_MAX_FIELDS); } // check at leaset one field value not empty bool checkFields = false; for (int i = 0; i < dataEntry.Fields.Length; i++) { if (dataEntry.Fields[i] != null) { checkFields = true; break; } } if (!checkFields) { throw new ArgumentNullException("fields", "You must specify a field value at least"); } // check status message if ((dataEntry.Status != null) && (dataEntry.Status.Length > THING_SPEAK_MAX_STATUS)) { throw new ArgumentException("status", "Max status length is " + THING_SPEAK_MAX_STATUS); } // check twitter account and message if (((dataEntry.Twitter == null) && (dataEntry.Tweet != null)) || ((dataEntry.Twitter != null) && (dataEntry.Tweet == null))) { throw new ArgumentException("twitter and tweet parameters must be both valued"); } // build body string body = String.Empty; // fields... for (int i = 0; i < dataEntry.Fields.Length; i++) { if ((dataEntry.Fields[i] != null) && (dataEntry.Fields[i] != String.Empty)) { if (i > 0) { body += "&"; } body += "field" + (i + 1) + "=" + dataEntry.Fields[i]; } } // ...location... if (dataEntry.Location != null) { body += "&lat=" + dataEntry.Location.Latitude + "&long=" + dataEntry.Location.Longitude + "&elevation=" + dataEntry.Location.Elevation; } // ...status... if (dataEntry.Status != null) { body += "&status=" + dataEntry.Status; } // ...twitter... if ((dataEntry.Twitter != null) && (dataEntry.Tweet != null)) { body += "&twitter=" + dataEntry.Twitter + "&tweet=" + dataEntry.Tweet; } // build HTTP request string request = "POST " + THING_SPEAK_UPDATE_PATH + " HTTP/1.1" + CRLF; request += "Host: " + THING_SPEAK_HOST + CRLF; request += "Connection: close" + CRLF; request += "X-THINGSPEAKAPIKEY: " + writeApiKey + CRLF; request += "Content-Type: application/x-www-form-urlencoded" + CRLF; request += "Content-Length: " + body.Length + CRLF; request += CRLF; request += body + CRLF; string result = String.Empty; // open socket e connect to the host using (this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { this.socket.Connect(this.hostIpEndPoint); // send HTTP request this.sendBuffer = Encoding.UTF8.GetBytes(request); if (this.SSL) { // TODO : HTTPS communication } else { // send HTTP request this.socket.Send(this.sendBuffer); // receive HTTP response this.receiveBuffer = new byte[RECEIVE_BUFFER_SIZE]; // poll on socket for reading (timeout 30 sec) while (this.socket.Poll(30 * 1000000, SelectMode.SelectRead)) { // no data on th socket (closed or timeout) if (this.socket.Available == 0) { break; } // empty buffer Array.Clear(this.receiveBuffer, 0, this.receiveBuffer.Length); // read data this.socket.Receive(this.receiveBuffer); // append response result += new String(Encoding.UTF8.GetChars(this.receiveBuffer)); } } } // decode HTTP response ThingSpeakHttpResponse httpResponse = ThingSpeakHttpResponse.Parse(result); Debug.Print(result); if (httpResponse.StatusCode == 200) { // set entry Id received from the server dataEntry.Id = Convert.ToInt32(httpResponse.Body); return(true); } else { return(false); } }
/// <summary> /// Update a channel /// </summary> /// <param name="writeApiKey">Write API Key for the channel to update</param> /// <param name="dataEntry">Data entry for updating channel</param> /// <returns>Update result</returns> public bool Update( string writeApiKey, DataEntry dataEntry) { // check for a mandatory write API Key if ((writeApiKey == null) || (writeApiKey == String.Empty)) throw new ArgumentNullException("writeApiKey", "You must specify a write API Key"); // check max fields number if (dataEntry.Fields.Length > THING_SPEAK_MAX_FIELDS) throw new ArgumentException("fields", "Max number of field is " + THING_SPEAK_MAX_FIELDS); // check at leaset one field value not empty bool checkFields = false; for (int i = 0; i < dataEntry.Fields.Length; i++) { if (dataEntry.Fields[i] != null) { checkFields = true; break; } } if (!checkFields) throw new ArgumentNullException("fields", "You must specify a field value at least"); // check status message if ((dataEntry.Status != null) && (dataEntry.Status.Length > THING_SPEAK_MAX_STATUS)) throw new ArgumentException("status", "Max status length is " + THING_SPEAK_MAX_STATUS); // check twitter account and message if (((dataEntry.Twitter == null) && (dataEntry.Tweet != null)) || ((dataEntry.Twitter != null) && (dataEntry.Tweet == null))) throw new ArgumentException("twitter and tweet parameters must be both valued"); // build body string body = String.Empty; // fields... for (int i = 0; i < dataEntry.Fields.Length; i++) { if ((dataEntry.Fields[i] != null) && (dataEntry.Fields[i] != String.Empty)) { if (i > 0) body += "&"; body += "field" + (i + 1) + "=" + dataEntry.Fields[i]; } } // ...location... if (dataEntry.Location != null) body += "&lat=" + dataEntry.Location.Latitude + "&long=" + dataEntry.Location.Longitude + "&elevation=" + dataEntry.Location.Elevation; // ...status... if (dataEntry.Status != null) body += "&status=" + dataEntry.Status; // ...twitter... if ((dataEntry.Twitter != null) && (dataEntry.Tweet != null)) body += "&twitter=" + dataEntry.Twitter + "&tweet=" + dataEntry.Tweet; // build HTTP request string request = "POST " + THING_SPEAK_UPDATE_PATH + " HTTP/1.1" + CRLF; request += "Host: " + THING_SPEAK_HOST + CRLF; request += "Connection: close" + CRLF; request += "X-THINGSPEAKAPIKEY: " + writeApiKey + CRLF; request += "Content-Type: application/x-www-form-urlencoded" + CRLF; request += "Content-Length: " + body.Length + CRLF; request += CRLF; request += body + CRLF; string result = String.Empty; // open socket e connect to the host using (this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { this.socket.Connect(this.hostIpEndPoint); // send HTTP request this.sendBuffer = Encoding.UTF8.GetBytes(request); if (this.SSL) { // TODO : HTTPS communication } else { // send HTTP request this.socket.Send(this.sendBuffer); // receive HTTP response this.receiveBuffer = new byte[RECEIVE_BUFFER_SIZE]; // poll on socket for reading (timeout 30 sec) while (this.socket.Poll(30 * 1000000, SelectMode.SelectRead)) { // no data on th socket (closed or timeout) if (this.socket.Available == 0) break; // empty buffer Array.Clear(this.receiveBuffer, 0, this.receiveBuffer.Length); // read data this.socket.Receive(this.receiveBuffer); // append response result += new String(Encoding.UTF8.GetChars(this.receiveBuffer)); } } } // decode HTTP response ThingSpeakHttpResponse httpResponse = ThingSpeakHttpResponse.Parse(result); Debug.Print(result); if (httpResponse.StatusCode == 200) { // set entry Id received from the server dataEntry.Id = Convert.ToInt32(httpResponse.Body); return true; } else return false; }
/// <summary> /// Read channel data entries /// </summary> /// <param name="readApiKey">Read API Key for the channel to read (null if channel is public)</param> /// <param name="channelId">Channel ID</param> /// <param name="path">Path for reading channel</param> /// <returns>List of all data entries read</returns> private ArrayList ReadChannel(string readApiKey, int channelId, string path) { // build HTTP request string request = "GET /channels/" + channelId + path + " HTTP/1.1" + CRLF; request += "Host: " + THING_SPEAK_HOST + CRLF; request += "Connection: close" + CRLF; if ((readApiKey != null) && (readApiKey != String.Empty)) { request += "X-THINGSPEAKAPIKEY: " + readApiKey + CRLF; } request += CRLF; string result = String.Empty; // open socket e connect to the host using (this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { this.socket.Connect(this.hostIpEndPoint); this.sendBuffer = Encoding.UTF8.GetBytes(request); if (this.SSL) { // TODO : HTTPS communication } else { // send HTTP request this.socket.Send(this.sendBuffer); // receive HTTP response this.receiveBuffer = new byte[RECEIVE_BUFFER_SIZE]; // poll on socket for reading (timeout 30 sec) while (this.socket.Poll(30 * 1000000, SelectMode.SelectRead)) { // no data on th socket (closed or timeout) if (this.socket.Available == 0) { break; } // empty buffer Array.Clear(this.receiveBuffer, 0, this.receiveBuffer.Length); // read data this.socket.Receive(this.receiveBuffer); // append response result += new String(Encoding.UTF8.GetChars(this.receiveBuffer)); } } } // decode HTTP response ThingSpeakHttpResponse httpResponse = ThingSpeakHttpResponse.Parse(result); Debug.Print(result); if (httpResponse.StatusCode == 200) { return(DataEntry.ParseCsv(httpResponse.Body)); } else { return(null); } }
/// <summary> /// Parse data entries in CSV format /// </summary> /// <param name="data">Data entries in CSV format</param> /// <returns>List of all data entries</returns> public static ArrayList ParseCsv(string data) { ArrayList dataEntries = new ArrayList(); int i = 0; // split response lines on line feed string[] lines = data.Split(LF); // extract column headers string[] headers = lines[i++].Split(','); while (i < lines.Length) { // extract token on current line string[] tokens = lines[i].Split(','); DataEntry dataEntry = new DataEntry(); // parse all tokens for (int j = 0; j < tokens.Length; j++) { // date/time if (headers[j] == "created_at") { // date/time in UTC format dataEntry.DateTime = DataEntry.Parse(tokens[j]); } // entry id else if (headers[j] == "entry_id") { dataEntry.Id = Convert.ToInt32(tokens[j]); } // any field (field1, field2, .... field8) else if (headers[j].Substring(0, 5) == "field") { int fieldIdx = Convert.ToInt32(headers[j].Substring(5, 1)); dataEntry.Fields[fieldIdx - 1] = tokens[j]; } // latitude else if (headers[j] == "latitude") { if (tokens[j] != String.Empty) { if (dataEntry.Location == null) { dataEntry.Location = new Location(); } dataEntry.Location.Latitude = Convert.ToDouble(tokens[j]); } } // longitude else if (headers[j] == "longitude") { if (tokens[j] != String.Empty) { if (dataEntry.Location == null) { dataEntry.Location = new Location(); } dataEntry.Location.Longitude = Convert.ToDouble(tokens[j]); } } // elevation else if (headers[j] == "elevation") { if (tokens[j] != String.Empty) { if (dataEntry.Location == null) { dataEntry.Location = new Location(); } dataEntry.Location.Elevation = Convert.ToDouble(tokens[j]); } } else if (headers[j] == "location") { // TODO } // status else if (headers[j] == "status") { if (tokens[j] != String.Empty) { dataEntry.Status = tokens[j]; } } } dataEntries.Add(dataEntry); i++; } return(dataEntries); }