Merge branch 'master' of github.com:iobridge/thingspeak
This commit is contained in:
commit
9d4b74d3da
@ -369,7 +369,6 @@ class ChannelsController < ApplicationController
|
|||||||
feed.longitude = params[:long] if params[:long]
|
feed.longitude = params[:long] if params[:long]
|
||||||
feed.longitude = params[:longitude] if params[:longitude]
|
feed.longitude = params[:longitude] if params[:longitude]
|
||||||
feed.elevation = params[:elevation] if params[:elevation]
|
feed.elevation = params[:elevation] if params[:elevation]
|
||||||
feed.location = params[:location] if params[:location]
|
|
||||||
|
|
||||||
# if the saves were successful
|
# if the saves were successful
|
||||||
if channel.save && feed.save
|
if channel.save && feed.save
|
||||||
@ -518,6 +517,14 @@ class ChannelsController < ApplicationController
|
|||||||
if !row.blank?
|
if !row.blank?
|
||||||
feed = Feed.new
|
feed = Feed.new
|
||||||
|
|
||||||
|
# set location and status then delete the rows
|
||||||
|
# these 5 deletes must be performed in the proper (reverse) order
|
||||||
|
feed.status = row.delete_at(status_column) if status_column > 0
|
||||||
|
feed.location = row.delete_at(location_column) if location_column > 0
|
||||||
|
feed.elevation = row.delete_at(elevation_column) if elevation_column > 0
|
||||||
|
feed.longitude = row.delete_at(longitude_column) if longitude_column > 0
|
||||||
|
feed.latitude = row.delete_at(latitude_column) if latitude_column > 0
|
||||||
|
|
||||||
# add the fields if they are from named columns, using reverse order
|
# add the fields if they are from named columns, using reverse order
|
||||||
feed.field8 = row.delete_at(field8_column) if field8_column != -1
|
feed.field8 = row.delete_at(field8_column) if field8_column != -1
|
||||||
feed.field7 = row.delete_at(field7_column) if field7_column != -1
|
feed.field7 = row.delete_at(field7_column) if field7_column != -1
|
||||||
@ -528,14 +535,6 @@ class ChannelsController < ApplicationController
|
|||||||
feed.field2 = row.delete_at(field2_column) if field2_column != -1
|
feed.field2 = row.delete_at(field2_column) if field2_column != -1
|
||||||
feed.field1 = row.delete_at(field1_column) if field1_column != -1
|
feed.field1 = row.delete_at(field1_column) if field1_column != -1
|
||||||
|
|
||||||
# set location and status then delete the rows
|
|
||||||
# these 5 deletes must be performed in the proper (reverse) order
|
|
||||||
feed.status = row.delete_at(status_column) if status_column > 0
|
|
||||||
feed.location = row.delete_at(location_column) if location_column > 0
|
|
||||||
feed.elevation = row.delete_at(elevation_column) if elevation_column > 0
|
|
||||||
feed.longitude = row.delete_at(longitude_column) if longitude_column > 0
|
|
||||||
feed.latitude = row.delete_at(latitude_column) if latitude_column > 0
|
|
||||||
|
|
||||||
# remove entry_id column if necessary
|
# remove entry_id column if necessary
|
||||||
row.delete_at(entry_id_column) if entry_id_column > 0
|
row.delete_at(entry_id_column) if entry_id_column > 0
|
||||||
|
|
||||||
@ -557,6 +556,10 @@ class ChannelsController < ApplicationController
|
|||||||
feed.field6 = row[6] if feed.field6.blank?
|
feed.field6 = row[6] if feed.field6.blank?
|
||||||
feed.field7 = row[7] if feed.field7.blank?
|
feed.field7 = row[7] if feed.field7.blank?
|
||||||
feed.field8 = row[8] if feed.field8.blank?
|
feed.field8 = row[8] if feed.field8.blank?
|
||||||
|
feed.latitude = row[9] if feed.latitude.blank?
|
||||||
|
feed.longitude = row[10] if feed.longitude.blank?
|
||||||
|
feed.elevation = row[11] if feed.elevation.blank?
|
||||||
|
feed.status = row[12] if feed.status.blank?
|
||||||
|
|
||||||
# save channel and feed
|
# save channel and feed
|
||||||
feed.save
|
feed.save
|
||||||
@ -615,4 +618,3 @@ class ChannelsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
class WindowsController < ApplicationController
|
class WindowsController < ApplicationController
|
||||||
before_filter :require_user, :except => [:index, :html, :iframe]
|
before_filter :require_user, :except => [:index, :html, :iframe]
|
||||||
|
|
||||||
|
# hides a window, returns the window id if successful or '-1' if failure
|
||||||
def hide
|
def hide
|
||||||
window = Window.find(params[:id])
|
window = Window.find(params[:id])
|
||||||
window.show_flag = false
|
window.show_flag = false
|
||||||
@ -11,60 +12,36 @@ class WindowsController < ApplicationController
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Call WindowsController.display when we want to display a window on the dashboard
|
# displays a window on the dashboard
|
||||||
# params[:visibility_flag] is whether it is the private or public dashboard
|
|
||||||
# params[:plugin] is for displaying a plugin, instead of a window
|
|
||||||
# params[:id] is the window ID for conventional windows, but the plugin_id for plugins
|
|
||||||
# params[:channel_id] is the channel_id
|
|
||||||
def display
|
def display
|
||||||
@visibility = params[:visibility_flag]
|
|
||||||
|
|
||||||
window = Window.find(params[:id])
|
window = Window.find(params[:id])
|
||||||
window = Window.new if window.nil?
|
|
||||||
window.show_flag = true
|
window.show_flag = true
|
||||||
#Just save this change, then modify the object before rendering the JSON
|
# save this change
|
||||||
savedWindow = window.save
|
saved_window = window.save
|
||||||
|
|
||||||
config_window window
|
# modify the object before rendering the JSON
|
||||||
|
window.set_title_for_display!
|
||||||
|
window.set_html_for_display!
|
||||||
|
|
||||||
@mychannel = current_user && current_user.id == window.channel.user_id
|
# if the window was saved successfully
|
||||||
|
if saved_window
|
||||||
if savedWindow
|
|
||||||
render :json => window.to_json
|
render :json => window.to_json
|
||||||
else
|
else
|
||||||
render :json => 'An error occurred'.to_json
|
render :json => 'An error occurred'.to_json
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def config_window(window)
|
|
||||||
if window.window_type == "plugin"
|
|
||||||
pluginName = Plugin.find(window.content_id).name
|
|
||||||
window.title = t(window.title, {:name => pluginName})
|
|
||||||
elsif window.window_type == "chart"
|
|
||||||
window.title = t(window.title, {:field_number => window.content_id})
|
|
||||||
options = window.options if !window.nil?
|
|
||||||
options ||= ""
|
|
||||||
window.html["::OPTIONS::"] = options unless window.html.nil? || window.html.index("::OPTIONS::").nil?
|
|
||||||
else
|
|
||||||
window.title = t(window.title)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def html
|
def html
|
||||||
window = Window.find(params[:id])
|
window = Window.find(params[:id])
|
||||||
options = window.options unless window.nil? || window.window_type != "chart"
|
window.set_html_for_display!
|
||||||
window.html["::OPTIONS::"] = options unless window.html.nil? || window.html.index("::OPTIONS::").nil?
|
render :text => window.html
|
||||||
html = window.html
|
|
||||||
|
|
||||||
render :text => html
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def iframe
|
def iframe
|
||||||
window = Window.find(params[:id])
|
window = Window.find(params[:id])
|
||||||
options = window.options unless window.nil? || window.window_type != "chart"
|
window.set_html_for_display!
|
||||||
window.html["::OPTIONS::"] = options unless window.html.nil? || window.html.index("::OPTIONS::").nil?
|
|
||||||
iframe_html = window.html
|
iframe_html = window.html
|
||||||
|
# set the domain correctly
|
||||||
iframe_html = iframe_html.gsub(/src=\"[\/.]/, 'src="' + api_domain);
|
iframe_html = iframe_html.gsub(/src=\"[\/.]/, 'src="' + api_domain);
|
||||||
render :text => iframe_html
|
render :text => iframe_html
|
||||||
end
|
end
|
||||||
@ -73,26 +50,16 @@ class WindowsController < ApplicationController
|
|||||||
channel = Channel.find(params[:channel_id])
|
channel = Channel.find(params[:channel_id])
|
||||||
windows = channel.public_windows(true).order(:position) unless params[:channel_id].nil?
|
windows = channel.public_windows(true).order(:position) unless params[:channel_id].nil?
|
||||||
|
|
||||||
if channel.recent_statuses.nil? || channel.recent_statuses.size <= 0
|
if channel.recent_statuses.blank?
|
||||||
@windows = windows.delete_if { |w| w.window_type == "status" }
|
@windows = windows.delete_if { |w| w.window_type == "status" }
|
||||||
else
|
else
|
||||||
@windows = windows
|
@windows = windows
|
||||||
end
|
end
|
||||||
|
|
||||||
@windows.each do |window|
|
@windows.each do |window|
|
||||||
|
# modify the object before rendering the JSON
|
||||||
if window.window_type == "plugin"
|
window.set_title_for_display!
|
||||||
pluginName = Plugin.find(window.content_id).name
|
window.set_html_for_display!
|
||||||
window.title = t(window.title, {:name => pluginName})
|
|
||||||
elsif window.window_type == "chart"
|
|
||||||
window.title = t(window.title, {:field_number => window.content_id})
|
|
||||||
options = window.options if !window.nil?
|
|
||||||
options ||= ""
|
|
||||||
window.html["::OPTIONS::"] = options unless window.html.nil? || window.html.index("::OPTIONS::").nil?
|
|
||||||
else
|
|
||||||
window.title = t(window.title)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
@ -108,21 +75,15 @@ class WindowsController < ApplicationController
|
|||||||
channel = Channel.find(params[:channel_id])
|
channel = Channel.find(params[:channel_id])
|
||||||
|
|
||||||
if @visibility == "private"
|
if @visibility == "private"
|
||||||
@windows = channel.private_windows(false) unless channel.nil?
|
@windows = channel.private_windows(false)
|
||||||
else
|
else
|
||||||
@windows = channel.public_windows(false) unless channel.nil?
|
@windows = channel.public_windows(false)
|
||||||
end
|
end
|
||||||
@windows.reject! { |window| window.window_type == "plugin" }
|
@windows.reject! { |window| window.window_type == "plugin" }
|
||||||
@windows.each do |window|
|
@windows.each do |window|
|
||||||
if window.window_type == "plugin"
|
# modify the object before rendering the JSON
|
||||||
elsif window.window_type == "chart"
|
window.set_title_for_display!
|
||||||
window.title = t(window.title, {:field_number => window.content_id})
|
window.set_html_for_display!
|
||||||
options = window.options unless window.nil?
|
|
||||||
options ||= ""
|
|
||||||
window.html["::OPTIONS::"] = options unless window.html.nil? || window.html.index("::OPTIONS::").nil?
|
|
||||||
else
|
|
||||||
window.title = t(window.title)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
@ -133,26 +94,18 @@ class WindowsController < ApplicationController
|
|||||||
|
|
||||||
def private_windows
|
def private_windows
|
||||||
channel = Channel.find(params[:channel_id])
|
channel = Channel.find(params[:channel_id])
|
||||||
windows = channel.private_windows(true).order(:position) unless params[:channel_id].nil?
|
windows = channel.private_windows(true).order(:position)
|
||||||
|
|
||||||
if channel.recent_statuses.nil? || channel.recent_statuses.size <= 0
|
if channel.recent_statuses.blank?
|
||||||
@windows = windows.delete_if { |w| w.window_type == "status" }
|
@windows = windows.delete_if { |w| w.window_type == "status" }
|
||||||
else
|
else
|
||||||
@windows = windows
|
@windows = windows
|
||||||
end
|
end
|
||||||
|
|
||||||
@windows.each do |window|
|
@windows.each do |window|
|
||||||
if window.window_type == "plugin"
|
# modify the object before rendering the JSON
|
||||||
pluginName = Plugin.find(window.content_id).name
|
window.set_title_for_display!
|
||||||
window.title = t(window.title, {:name => pluginName})
|
window.set_html_for_display!
|
||||||
elsif window.window_type == "chart"
|
|
||||||
window.title = t(window.title, {:field_number => window.content_id})
|
|
||||||
options = window.options unless window.nil?
|
|
||||||
options ||= ""
|
|
||||||
window.html["::OPTIONS::"] = options unless window.html.nil? || window.html.index("::OPTIONS::").nil?
|
|
||||||
else
|
|
||||||
window.title = t(window.title)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
@ -163,7 +116,6 @@ class WindowsController < ApplicationController
|
|||||||
|
|
||||||
|
|
||||||
def update
|
def update
|
||||||
logger.info "We're trying to update the windows with " + params.to_s
|
|
||||||
#params for this put are going to look like
|
#params for this put are going to look like
|
||||||
# page"=>"{\"col\":0,\"positions\":[1,2,3]}"
|
# page"=>"{\"col\":0,\"positions\":[1,2,3]}"
|
||||||
#So.. the position values are Windows.id They should get updated with the ordinal value based
|
#So.. the position values are Windows.id They should get updated with the ordinal value based
|
||||||
@ -177,21 +129,20 @@ class WindowsController < ApplicationController
|
|||||||
values = JSON(params[:page])
|
values = JSON(params[:page])
|
||||||
|
|
||||||
# .. then find each window and update with new ordinal position and col.
|
# .. then find each window and update with new ordinal position and col.
|
||||||
logger.info "Channel id = " + params[:channel_id].to_s
|
|
||||||
@channel = current_user.channels.find(params[:channel_id])
|
@channel = current_user.channels.find(params[:channel_id])
|
||||||
col = values["col"]
|
col = values["col"]
|
||||||
saved = true
|
saved = true
|
||||||
values["positions"].each_with_index do |p,i|
|
values["positions"].each_with_index do |p, index|
|
||||||
windows = @channel.windows.where({:id => p}) unless p.nil?
|
window = @channel.windows.where({:id => p}).first unless p.nil?
|
||||||
unless windows.nil? || windows.empty?
|
if window.present?
|
||||||
w = windows[0]
|
window.position = index
|
||||||
w.position = i
|
window.col = col
|
||||||
w.col = col
|
if !window.save
|
||||||
if !w.save
|
|
||||||
saved = false
|
saved = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
# if the windows were saved successfully
|
||||||
if saved
|
if saved
|
||||||
render :text => '0'
|
render :text => '0'
|
||||||
else
|
else
|
||||||
|
@ -48,7 +48,7 @@ class Feed < ActiveRecord::Base
|
|||||||
# for to_xml, return only the public attributes
|
# for to_xml, return only the public attributes
|
||||||
def self.public_options
|
def self.public_options
|
||||||
{
|
{
|
||||||
:except => [:id, :updated_at]
|
:except => [:id, :updated_at, :location]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -70,7 +70,6 @@ class Feed < ActiveRecord::Base
|
|||||||
only += [:latitude]
|
only += [:latitude]
|
||||||
only += [:longitude]
|
only += [:longitude]
|
||||||
only += [:elevation]
|
only += [:elevation]
|
||||||
only += [:location]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# add status if necessary
|
# add status if necessary
|
||||||
|
@ -43,5 +43,29 @@ class Window < ActiveRecord::Base
|
|||||||
window if window.save
|
window if window.save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# set the title for display to user; don't save after calling this method
|
||||||
|
def set_title_for_display!
|
||||||
|
# if this is a plugin
|
||||||
|
if window_type == "plugin"
|
||||||
|
plugin_name = Plugin.find(content_id).name
|
||||||
|
self.title = I18n.t(title, {:name => plugin_name})
|
||||||
|
# else if this is a chart
|
||||||
|
elsif window_type == "chart"
|
||||||
|
self.title = I18n.t(title, {:field_number => content_id})
|
||||||
|
# else set title for other window types, for example: I18n.t('window_map') = 'Channel Location'
|
||||||
|
else
|
||||||
|
self.title = I18n.t(title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# set the html for display to user; don't save after calling this method
|
||||||
|
def set_html_for_display!
|
||||||
|
if window_type == "chart"
|
||||||
|
html_options = options || ''
|
||||||
|
# replace '::OPTIONS::' if present
|
||||||
|
self.html['::OPTIONS::'] = html_options if html.present? && html.index("::OPTIONS::").present?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -8,11 +8,15 @@ To view a specific Channel, send an HTTP GET to
|
|||||||
<br>
|
<br>
|
||||||
<code><%= @ssl_api_domain %>channels/<span class="customcode">CHANNEL_ID</span><span class="format format-json">.json</span><span class="format format-xml">.xml</span></code> .
|
<code><%= @ssl_api_domain %>channels/<span class="customcode">CHANNEL_ID</span><span class="format format-json">.json</span><span class="format format-xml">.xml</span></code> .
|
||||||
|
|
||||||
<br><br>
|
<br>
|
||||||
Valid parameters:
|
|
||||||
<ul>
|
<div class="format format-json format-xml">
|
||||||
|
<br>
|
||||||
|
Valid parameters:
|
||||||
|
<ul>
|
||||||
<li><b>api_key</b> (string) - User's API Key; please note that this is different than a Channel API key, and can be found in <a href="/account">your account details</a>. If this key is provided, the Channel's private details (such as the Channel's API keys) will also be shown. (optional).</li>
|
<li><b>api_key</b> (string) - User's API Key; please note that this is different than a Channel API key, and can be found in <a href="/account">your account details</a>. If this key is provided, the Channel's private details (such as the Channel's API keys) will also be shown. (optional).</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
Example GET:
|
Example GET:
|
||||||
|
@ -64,8 +64,7 @@ POST <span class="str"><%= @ssl_api_domain %>update<span class="format format-js
|
|||||||
"status": null,
|
"status": null,
|
||||||
"latitude": null,
|
"latitude": null,
|
||||||
"longitude": null,
|
"longitude": null,
|
||||||
"elevation": null,
|
"elevation": null
|
||||||
"location":null
|
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -92,7 +91,6 @@ POST <span class="str"><%= @ssl_api_domain %>update<span class="format format-js
|
|||||||
<latitude type="decimal" nil="true"/>
|
<latitude type="decimal" nil="true"/>
|
||||||
<longitude type="decimal" nil="true"/>
|
<longitude type="decimal" nil="true"/>
|
||||||
<elevation nil="true"/>
|
<elevation nil="true"/>
|
||||||
<location nil="true"/>
|
|
||||||
</feed>
|
</feed>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
69
app/views/docs/thingtweet.html.erb
Normal file
69
app/views/docs/thingtweet.html.erb
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-sm-offset-1 col-sm-3 col-xs-12" id="leftcol">
|
||||||
|
<%= render 'docs/sidebar' %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-7 col-xs-12">
|
||||||
|
|
||||||
|
<h1 id="thingtweet">ThingTweet</h1>
|
||||||
|
|
||||||
|
The ThingTweet App allows you to update a Twitter status via ThingSpeak. Twitter requires Open Authentication (OAuth) which is difficult for a low level device to interface with. ThingTweet acts a Twitter proxy, so the device can use Twitter by making simple API calls.
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
<h2 id="setup">App Setup</h2>
|
||||||
|
|
||||||
|
Sign in to <a href="https://thingspeak.com/login">ThingSpeak</a>, select Apps from the menu, and then click on <a href="https://thingspeak.com/apps/thingtweet">ThingTweet</a>.
|
||||||
|
<br><br>
|
||||||
|
Under the ThingTweet App, select "Link new Twitter account". This will redirect you to Twitter to see if you want the app to have the ability to access your account. You can Allow or Deny the process. Once you have confirmed the right Twitter account, Twitter will send you back to ThingSpeak.
|
||||||
|
<br><br>
|
||||||
|
The app generates a ThingTweet API Key for you to use. If you send an HTTP POST with your ThingTweet API Key, then the message will be relayed to Twitter. All of the parameters from the Twitter API (<a href="https://dev.twitter.com/rest/reference/post/statuses/update">statuses/update</a>) are possible including geolocation.
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<hr />
|
||||||
|
<h2 id="update">Update Twitter Status</h2>
|
||||||
|
|
||||||
|
To update your Twitter status send an HTTP POST to <code><%= @ssl_api_domain %>apps/thingtweet/1/statuses/update</code> and include your ThingTweet API key and message.
|
||||||
|
<br><br>
|
||||||
|
Example POST:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
POST <span class="str"><%= @ssl_api_domain %>apps/thingtweet/1/statuses/update</span>
|
||||||
|
api_key=<span class="customcode"><%= @thingtweet_api_key %></span>
|
||||||
|
status=<span class="customcode">I just posted this from my thing!</span></pre>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
The response will be <code>1</code> if the update was successful, and <code>-1</code> if there was an error.
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<h4>Channel Values</h4>
|
||||||
|
You can retrieve the last value from a Channel field by including the following in the ThingTweet status:
|
||||||
|
<br><br>
|
||||||
|
<code>%%channel_<span class="customcode">CHANNEL_ID</span>_field_<span class="customcode">FIELD_NUMBER</span>%%</code>
|
||||||
|
<br><br>
|
||||||
|
For example, you can send a Tweet that includes the last value from Channel 1417, field 1:
|
||||||
|
<br><br>
|
||||||
|
<code>status=The current CheerLights color is %%channel_<span class="customcode">1417</span>_field_<span class="customcode">1</span>%%.</code>
|
||||||
|
|
||||||
|
<br><br>
|
||||||
|
<hr />
|
||||||
|
<h2>Update Channel Feed and Twitter Status</h2>
|
||||||
|
Your Twitter status can also be updated when a <a href="/docs/channels#update">Channel feed is updated</a> by specifying the <i>twitter</i> and <i>tweet</i> parameters.
|
||||||
|
<br><br>
|
||||||
|
Example Channel feed update that also updates a Twitter status:
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
POST <span class="str"><%= @ssl_api_domain %>update<span class="format format-json">.json</span><span class="format format-xml">.xml</span></span>
|
||||||
|
api_key=<span class="customcode">XXXXXXXXXXXXXXXX</span>
|
||||||
|
field1=<span class="customcode">73</span>
|
||||||
|
twitter=<span class="customcode">thingspeaktest</span>
|
||||||
|
tweet=<span class="customcode">I just posted this from my thing!</span>
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<br><br><br><br><br><br><br><br><br><br><br><br>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -26,6 +26,7 @@
|
|||||||
<li><a title="CheerLights with Arduino and the FastLED Library" href="http://community.thingspeak.com/tutorials/arduino/cheerlights-with-arduino-and-the-fastled-library/" target="_blank">CheerLights with Arduino and the FastLED Library</a></li>
|
<li><a title="CheerLights with Arduino and the FastLED Library" href="http://community.thingspeak.com/tutorials/arduino/cheerlights-with-arduino-and-the-fastled-library/" target="_blank">CheerLights with Arduino and the FastLED Library</a></li>
|
||||||
<li><a title="RESTduino to ThingSpeak via Python" href="https://github.com/sirleech/RestduinoThingspeak" target="_blank">RESTduino to ThingSpeak via Python</a> [external]</li>
|
<li><a title="RESTduino to ThingSpeak via Python" href="https://github.com/sirleech/RestduinoThingspeak" target="_blank">RESTduino to ThingSpeak via Python</a> [external]</li>
|
||||||
<li><a title="Arduino ThingSpeak Example Source Code is on GitHub" href="https://github.com/iobridge/ThingSpeak-Arduino-Examples" target="_blank">Arduino Examples for ThingSpeak on GitHub</a> [external]</li>
|
<li><a title="Arduino ThingSpeak Example Source Code is on GitHub" href="https://github.com/iobridge/ThingSpeak-Arduino-Examples" target="_blank">Arduino Examples for ThingSpeak on GitHub</a> [external]</li>
|
||||||
|
<li><a title="Freetronics Eleven Review and ThingSpeak Project" href="http://community.thingspeak.com/tutorials/freetronics/freetronics-eleven-review-and-thingspeak-project/">Freetronics Eleven Arduino Review and ThingSpeak Project</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>C</h3>
|
<h3>C</h3>
|
||||||
<ul>
|
<ul>
|
||||||
@ -42,10 +43,6 @@
|
|||||||
<li><a title="Battery-powered Temperature Logger with ThingSpeak + Electric Imp" href="http://www.slickstreamer.info/2014/01/simpel-electric-imp-temperature-logger.html">Battery-powered Temperature Logger with ThingSpeak + Electric Imp</a> [external]</li>
|
<li><a title="Battery-powered Temperature Logger with ThingSpeak + Electric Imp" href="http://www.slickstreamer.info/2014/01/simpel-electric-imp-temperature-logger.html">Battery-powered Temperature Logger with ThingSpeak + Electric Imp</a> [external]</li>
|
||||||
<li><a title="Solar-powered Temperature Logger with Electric Imp and ThingSpeak" href="https://gist.github.com/evilmachina/6402955">Solar-powered Temperature Logger with Electric Imp and ThingSpeak</a> [external]</li>
|
<li><a title="Solar-powered Temperature Logger with Electric Imp and ThingSpeak" href="https://gist.github.com/evilmachina/6402955">Solar-powered Temperature Logger with Electric Imp and ThingSpeak</a> [external]</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>Freetronics</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a title="Freetronics Eleven Review and ThingSpeak Project" href="http://community.thingspeak.com/tutorials/freetronics/freetronics-eleven-review-and-thingspeak-project/">Freetronics Eleven Review and ThingSpeak Project</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Google</h3>
|
<h3>Google</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a title="Google Gauge Visualization for a ThingSpeak Channel" href="http://community.thingspeak.com/google/display-a-google-gauge-visualization-using-thingspeak-plugins/">Display a Google Gauge Visualization using ThingSpeak Plugins</a></li>
|
<li><a title="Google Gauge Visualization for a ThingSpeak Channel" href="http://community.thingspeak.com/google/display-a-google-gauge-visualization-using-thingspeak-plugins/">Display a Google Gauge Visualization using ThingSpeak Plugins</a></li>
|
||||||
@ -107,6 +104,10 @@
|
|||||||
<li><a title="Using Arduino and Python to Update a ThingSpeak Channel" href="http://vimeo.com/19064691" target="_blank">Using Arduino and Python to Update a ThingSpeak Channel</a> </li>
|
<li><a title="Using Arduino and Python to Update a ThingSpeak Channel" href="http://vimeo.com/19064691" target="_blank">Using Arduino and Python to Update a ThingSpeak Channel</a> </li>
|
||||||
<li><a title="Connecting Arduino to Thingspeak using python as an middle ware" href="http://tenettech.com/blogspot/?p=918" target="_blank">Connecting Arduino to ThingSpeak using Python as Middle-ware</a> [external]</li>
|
<li><a title="Connecting Arduino to Thingspeak using python as an middle ware" href="http://tenettech.com/blogspot/?p=918" target="_blank">Connecting Arduino to ThingSpeak using Python as Middle-ware</a> [external]</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<h3>Raspberry Pi</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a title="ThingSpeak Temperature with Raspberry Pi" href="http://www.dexterindustries.com/BrickPi/projects/thingspeak-temperature-log/" target="_blank">ThingSpeak Temperature with Raspberry Pi and BrickPi</a> [external]</li>
|
||||||
|
</ul>
|
||||||
<h3>Ruby</h3>
|
<h3>Ruby</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a title="ThingSpeak Ruby Gem" href="http://community.thingspeak.com/tutorials/ruby/thingspeak-api-ruby-gem/" target="_blank">ThingSpeak API Ruby Gem</a></li>
|
<li><a title="ThingSpeak Ruby Gem" href="http://community.thingspeak.com/tutorials/ruby/thingspeak-api-ruby-gem/" target="_blank">ThingSpeak API Ruby Gem</a></li>
|
||||||
@ -117,7 +118,8 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<h3>Spark Core</h3>
|
<h3>Spark Core</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a title="Spark Core Interface for ThingSpeak" href="https://community.spark.io/t/interface-for-thingspeak/2329">Spark Core Interface for ThingSpeak</a> [external [beta]</li>
|
<li><a title="Control, monitor, and log a Spark Core with ThingSpeak" href="http://community.spark.io/t/control-monitor-and-log-a-spark-core-with-thingspeak/10543">Control and Monitor a Spark Core with ThingSpeak</a> [external] [beta]</li>
|
||||||
|
<li><a title="Spark Core Interface for ThingSpeak" href="https://community.spark.io/t/interface-for-thingspeak/2329">Spark Core Interface for ThingSpeak</a> [external] [beta]</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>Twine</h3>
|
<h3>Twine</h3>
|
||||||
<ul>
|
<ul>
|
||||||
@ -136,6 +138,10 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li><a title="How to Embed a ThingSpeak Chart on your WordPress Blog" href="http://community.thingspeak.com/wordpress/how-to-embed-a-thingspeak-chart-on-your-wordpress-blog/">How to Embed a ThingSpeak Chart on your WordPress Blog</a></li>
|
<li><a title="How to Embed a ThingSpeak Chart on your WordPress Blog" href="http://community.thingspeak.com/wordpress/how-to-embed-a-thingspeak-chart-on-your-wordpress-blog/">How to Embed a ThingSpeak Chart on your WordPress Blog</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<h3>Windows PowerShell</h3>
|
||||||
|
<ul>
|
||||||
|
<li><a title="Send data to ThingSpeak from a Windows PowerShell Script" href="https://github.com/nothans/ThingSpeak-PowerShell">Send Data to ThingSpeak from a Windows PowerShell Script</a></li>
|
||||||
|
</ul>
|
||||||
<h3>Wireless</h3>
|
<h3>Wireless</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a title="Connecting XBee Wireless Networks to ThingSpeak via the ConnectPort X2 running XIG" href="http://community.thingspeak.com/tutorials/wireless/connecting-xbee-wireless-networks-to-thingspeak-via-the-connectport-x2-running-xig/">Connecting XBee Wireless Networks to ThingSpeak via the ConnectPort X2 running XIG</a></li>
|
<li><a title="Connecting XBee Wireless Networks to ThingSpeak via the ConnectPort X2 running XIG" href="http://community.thingspeak.com/tutorials/wireless/connecting-xbee-wireless-networks-to-thingspeak-via-the-connectport-x2-running-xig/">Connecting XBee Wireless Networks to ThingSpeak via the ConnectPort X2 running XIG</a></li>
|
||||||
|
@ -15,16 +15,13 @@
|
|||||||
|
|
||||||
// add click handler
|
// add click handler
|
||||||
$(document).on('click', '.ioplugin', function() {
|
$(document).on('click', '.ioplugin', function() {
|
||||||
|
|
||||||
var plugins = $(".plugin");
|
var plugins = $(".plugin");
|
||||||
var addPlugin = $(this);
|
var addPlugin = $(this);
|
||||||
var ids = addPlugin.attr('id').split("-");
|
var ids = addPlugin.attr('id').split("-");
|
||||||
var channelId = <%= params[:channel_id] %>;
|
var channelId = <%= params[:channel_id] %>;
|
||||||
var windowId =ids[1];
|
var windowId = ids[1];
|
||||||
//Need to add data to this request to identify it as a plugin request
|
|
||||||
var data = {plugin:true, visibility_flag:"<%= @visibility %>"};
|
$.update("/channels/" + channelId + "/windows/"+ windowId + "/display", {}, function(response) {
|
||||||
$.update("/channels/" + channelId + "/windows/"+ windowId + "/display" , data,
|
|
||||||
function(response) {
|
|
||||||
|
|
||||||
var window = response.window;
|
var window = response.window;
|
||||||
var window_type = window.window_type;
|
var window_type = window.window_type;
|
||||||
@ -79,7 +76,7 @@
|
|||||||
<div id="tabs">
|
<div id="tabs">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#tabs-1">Windows</a></li>
|
<li><a href="#tabs-1">Windows</a></li>
|
||||||
<% if @visibility =="private" %>
|
<% if @visibility == "private" %>
|
||||||
<li><a href="/plugins/private_plugins?channel_id=<%= params[:channel_id] %>">Plugins</a></li>
|
<li><a href="/plugins/private_plugins?channel_id=<%= params[:channel_id] %>">Plugins</a></li>
|
||||||
<% else %>
|
<% else %>
|
||||||
<li><a href="/plugins/public_plugins?channel_id=<%= params[:channel_id] %>">Plugins</a></li>
|
<li><a href="/plugins/public_plugins?channel_id=<%= params[:channel_id] %>">Plugins</a></li>
|
||||||
|
@ -26,6 +26,11 @@ require 'spec_helper'
|
|||||||
|
|
||||||
describe Feed do
|
describe Feed do
|
||||||
|
|
||||||
|
it "should not include location in feed.to_json" do
|
||||||
|
feed = Feed.new
|
||||||
|
JSON.parse(feed.to_json).keys.include?('location').should eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
it "should close the connection when an exception is raised" do
|
it "should close the connection when an exception is raised" do
|
||||||
# use a single connection for both queries
|
# use a single connection for both queries
|
||||||
connection = ActiveRecord::Base.connection
|
connection = ActiveRecord::Base.connection
|
||||||
|
Loading…
Reference in New Issue
Block a user