Skip to content

Instantly share code, notes, and snippets.

@niksm7
Last active August 3, 2022 14:56
Show Gist options
  • Save niksm7/dc2173e31624079295329cebc3d33f54 to your computer and use it in GitHub Desktop.
Save niksm7/dc2173e31624079295329cebc3d33f54 to your computer and use it in GitHub Desktop.
This file contains the code for the ThingSpeak Pack which integrates functionality of ThingSpeak platform with coda
import * as coda from "@codahq/packs-sdk";
export const pack = coda.newPack();
// Allow requests to the thingspeak API.
pack.addNetworkDomain("thingspeak.com");
// Setup per-user api key to be used in making requests
pack.setUserAuthentication({
type: coda.AuthenticationType.Custom,
params: [
{ name: "user_api_key", description: "The API key" },
],
instructionsUrl: "https://thingspeak.com/account/profile"
});
// Schema for sync table that displays channels
const ChannelSchema = coda.makeObjectSchema({
properties: {
id: { type: coda.ValueType.Number },
name: { type: coda.ValueType.String },
description: { type: coda.ValueType.String },
latitude: { type: coda.ValueType.String },
longitude: { type: coda.ValueType.String },
created_at: { type: coda.ValueType.String, codaType: coda.ValueHintType.DateTime },
elevation: { type: coda.ValueType.String },
last_entry_id: { type: coda.ValueType.Number },
public_flag: { type: coda.ValueType.Boolean },
url: { type: coda.ValueType.String },
ranking: { type: coda.ValueType.Number },
metadata: { type: coda.ValueType.String },
license_id: { type: coda.ValueType.Number },
github_url: { type: coda.ValueType.String },
tags: {
type: coda.ValueType.Array,
items: coda.makeSchema({ type: coda.ValueType.String }),
},
api_keys: {
type: coda.ValueType.Array,
items: coda.makeSchema({ type: coda.ValueType.String })
}
},
displayProperty: "id",
idProperty: "id",
featuredProperties: ["name", "description", "created_at", "last_entry_id", "public_flag", "api_keys"],
})
// Schema for sync table displaying channel data
const ChannelDataSchema = coda.makeObjectSchema({
properties: {
channel: {
type: coda.ValueType.String,
},
feeds: {
type: coda.ValueType.Array,
items: coda.makeSchema({ type: coda.ValueType.String }),
},
},
displayProperty: "channel",
idProperty: "channel",
featuredProperties: [],
})
// Schema of Alert history sync table
const AlertHistorySchema = coda.makeObjectSchema({
properties: {
requestedAt: {
type: coda.ValueType.String,
codaType: coda.ValueHintType.DateTime
},
sentAt: {
type: coda.ValueType.String,
codaType: coda.ValueHintType.DateTime
},
subject: {
type: coda.ValueType.String,
},
status: {
type: coda.ValueType.String,
},
},
displayProperty: "requestedAt",
idProperty: "requestedAt",
featuredProperties: ["requestedAt", "sentAt", "subject", "status"],
})
// List of common parameters that are used at different places
let common_parameters = [
coda.makeParameter({
type: coda.ParameterType.Number,
name: "ChannelId",
description: "Channel ID for the channel of interest.",
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "FieldId",
description: "Field ID for the field of interest.",
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "results",
description: "Number of entries to retrieve. The maximum number is 8000. The default is 100.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "days",
description: "Number of 24-hour periods before now to include in feed.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Date,
name: "start",
description: "Start date in format YYYY-MM-DD%20HH:NN:SS.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Date,
name: "end",
description: "End date in format YYYY-MM-DD%20HH:NN:SS.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "offset",
description: "Timezone offset used to display results. Use the timezone parameter for greater accuracy.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "min",
description: "Minimum value to include in response.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "max",
description: "Maximum value to include in response.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "round",
description: "Round to this many decimal places.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "timescale",
description: "Get first value in this many minutes. The valid values are: 10, 15, 20, 30, 60, 240, 720, 1440, 'daily'.",
optional: true,
autocomplete: ["10", "15", "20", "30", "60", "240", "720", "1440", "daily"]
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "sum",
description: "Get sum of this many minutes. The valid values are: 10, 15, 20, 30, 60, 240, 720, 1440, 'daily'.",
optional: true,
autocomplete: ["10", "15", "20", "30", "60", "240", "720", "1440", "daily"]
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "average",
description: "Get average of this many minutes. The valid values are 10, 15, 20, 30, 60, 240, 720, 1440, 'daily'. \
Note: NaN values are interpreted as 0 when calculating the average.",
optional: true,
autocomplete: ["10", "15", "20", "30", "60", "240", "720", "1440", "daily"]
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "median",
description: "Get median of this many minutes. The valid values are: 10, 15, 20, 30, 60, 240, 720, 1440, 'daily'",
optional: true,
autocomplete: ["10", "15", "20", "30", "60", "240", "720", "1440", "daily"]
}),
]
// Function to get the channel API key
async function getChannelAPI(ChannelId, context) {
let invocationToken = context.invocationToken;
let user_api_key = "{{user_api_key-" + invocationToken + "}}";
let response = await context.fetcher.fetch({
method: "GET",
url: "https://api.thingspeak.com/channels/" + ChannelId + ".json?api_key=" + user_api_key,
cacheTtlSecs: 240
});
return response.body.api_keys[1].api_key;
}
// Function used to add query parameters to the url
function queryStringParameters(urls_string, results, days, start, end, offset, min, max, round, timescale, sum, average, median) {
if (results != undefined) {
urls_string += "&results=" + results
}
if (days != undefined) {
urls_string += "&days=" + days
}
if (start != undefined) {
urls_string += "&start=" + start
}
if (end != undefined) {
urls_string += "&end=" + end
}
if (offset != undefined) {
urls_string += "&offset=" + offset
}
if (min != undefined) {
urls_string += "&min=" + min
}
if (max != undefined) {
urls_string += "&max=" + max
}
if (round != undefined) {
urls_string += "&round=" + round
}
if (timescale != undefined) {
urls_string += "&timescale=" + timescale
}
if (sum != undefined) {
urls_string += "&sum=" + sum
}
if (average != undefined) {
urls_string += "&average=" + average
}
if (median != undefined) {
urls_string += "&median=" + median
}
return urls_string
}
// Formula that generates charts for channels and allows customization
pack.addFormula({
name: "CreateChart",
description: "Generate charts for different channels with customization.",
resultType: coda.ValueType.String,
schema: {
type: coda.ValueType.String,
codaType: coda.ValueHintType.Embed,
force: true,
},
parameters: [
common_parameters[0],
common_parameters[1],
coda.makeParameter({
type: coda.ParameterType.Boolean,
name: "dynamic",
description: "Make chart update automatically based on the time interval mentioned in update. The default is false.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "update",
description: "Time interval in seconds to update the chart automatically. The default is 15.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "title",
description: "Chart title. The default is the channel name.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "xaxis_label",
description: "Chart x-axis label. The default is 'Date'.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "yaxis_label",
description: "Chart y-axis label. The default is the field name.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "color",
description: "Hex Value for line color. The default is FF000 (red).",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "bgcolor",
description: "Background color. The default is white.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "chart_type",
description: "Type of chart. The default is line.",
optional: true,
autocomplete: ["line", "bar", "column", "spline"],
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "width",
description: "Chart width in pixels, iframe width is 20 px larger, default chart width: 400. \
Set to auto to automatically adjust chart size based on its parent container.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "height",
description: "Chart height in pixels, iframe height is 20 px larger, default chart height: 200. \
Set to auto to automatically adjust chart size based on its parent container.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Boolean,
name: "step",
description: "Draw chart as a step chart. The default is false.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "yaxis_min",
description: "Minimum value of chart Y-Axis. If blank, the value is auto-calculated.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "yaxis_max",
description: "Maximum value of chart Y-Axis. If blank, the value is auto-calculated.",
optional: true,
}),
common_parameters[2],
common_parameters[3],
common_parameters[4],
common_parameters[5],
common_parameters[6],
common_parameters[7],
common_parameters[8],
common_parameters[9],
common_parameters[10],
common_parameters[11],
common_parameters[12],
common_parameters[13],
],
execute: async function ([ChannelId, FieldId, dynamic, update, title, xaxis_label, yaxis_label, color, bgcolor, chart_type,
width, height, step, yaxis_min, yaxis_max, results, days, start, end, offset, min, max, round, timescale, sum, average, median], context) {
let url_string = "https://api.thingspeak.com/channels/" + ChannelId + "/charts/" + FieldId + "?api_key=" + await getChannelAPI(ChannelId, context)
if (dynamic != undefined) {
url_string += "&dynamic=" + dynamic
}
if (update != undefined) {
url_string += "&update=" + update
}
if (title != undefined) {
url_string += "&title=" + title
}
if (xaxis_label != undefined) {
url_string += "&xaxis=" + xaxis_label
}
if (yaxis_label != undefined) {
url_string += "&yaxis=" + yaxis_label
}
if (color != undefined) {
url_string += "&color=" + color
}
if (bgcolor != undefined) {
url_string += "&bgcolor=" + bgcolor
}
if (chart_type != undefined) {
url_string += "&type=" + chart_type
}
if (width != undefined) {
url_string += "&width=" + width
}
if (height != undefined) {
url_string += "&height=" + height
}
if (step != undefined) {
url_string += "&step=" + step
}
if (yaxis_min != undefined) {
url_string += "&yaxismin=" + yaxis_min
}
if (yaxis_max != undefined) {
url_string += "&yaxismax=" + yaxis_max
}
url_string = queryStringParameters(url_string, results, days, start, end, offset, min, max, round, timescale, sum, average, median)
return url_string
},
});
// Formula that generates a channel map
pack.addFormula({
name: "CreateChannelMap",
description: "Show channel location on map",
resultType: coda.ValueType.String,
schema: {
type: coda.ValueType.String,
codaType: coda.ValueHintType.Embed,
force: true,
},
parameters: [
common_parameters[0],
coda.makeParameter({
type: coda.ParameterType.Number,
name: "width",
description: "Map width in pixels. Default map width is 450.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "height",
description: "Chart height in pixels. Default map height is 260.",
optional: true,
}),
],
execute: async function ([ChannelId, width, height], context) {
let url_string = "https://thingspeak.com/channels/" + ChannelId + "/maps/channel_show?read_api_key=" + await getChannelAPI(ChannelId, context)
if (width != undefined) {
url_string += "&width=" + width
}
if (height != undefined) {
url_string += "&height=" + height
}
return url_string
}
});
// Sync table that displays all the channels with their information
pack.addSyncTable({
name: "Channels",
identityName: "Channels",
schema: ChannelSchema,
formula: {
name: "SyncChannels",
description: "List all your channels.",
parameters: [],
execute: async function ([], context) {
let invocationToken = context.invocationToken;
let user_api_key = "{{user_api_key-" + invocationToken + "}}";
let url = "https://api.thingspeak.com/channels.json?api_key=" + user_api_key;
let response = await context.fetcher.fetch({
method: "GET",
url: url,
cacheTtlSecs: 0,
});
let items = response.body;
if (items != []) {
return {
result: items,
};
}
else {
throw new coda.UserVisibleError("The table has no data to display!");
}
}
}
})
// Formula that updates the settings of a channel
pack.addFormula({
name: "WriteChannelSetting",
description: "Update your channel settings",
resultType: coda.ValueType.String,
isAction: true,
parameters: [
common_parameters[0],
coda.makeParameter({
type: coda.ParameterType.String,
name: "name",
description: "Name of the channel.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "description",
description: "Description of the channel.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "url",
description: "Webpage URL for the channel.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "latitude",
description: "Latitude in degrees, specified as a value between -90 and 90.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "longitude",
description: "Longitude in degrees, specified as a value between -180 and 180.",
optional: true,
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "public_flag",
description: "Whether the channel is public. The default is false.",
optional: true,
}),
],
execute: async function ([ChannelId, name, description, url, latitude, longitude, public_flag], context) {
let url_string = "https://api.thingspeak.com/channels/" + ChannelId + ".json"
let invocationToken = context.invocationToken;
let user_api_key = "{{user_api_key-" + invocationToken + "}}";
let payload = {
"api_key": user_api_key,
};
if (name != undefined) {
payload["name"] = name
}
if (description != undefined) {
payload["description"] = description
}
if (url != undefined) {
payload["url"] = url
}
if (longitude != undefined) {
payload["longitude"] = String(longitude)
}
if (latitude != undefined) {
payload["latitude"] = String(latitude)
}
if (public_flag != undefined) {
payload["public_flag"] = public_flag
}
let response = await context.fetcher.fetch({
method: "PUT",
url: url_string,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
form: payload
});
if (response.status == 200) {
return "Updation successfull"
}
else {
return "Something went wrong!"
}
}
});
// Sync table that displays data of a channel
pack.addSyncTable({
name: "ChannelData",
identityName: "ChannelData",
schema: ChannelDataSchema,
dynamicOptions: {
getSchema: async function (context, _, { ChannelId }) {
let url_string = "https://api.thingspeak.com/channels/" + ChannelId + "/feeds.json?api_key=" + await getChannelAPI(ChannelId, context)
let response = await context.fetcher.fetch({
method: "GET",
url: url_string,
cacheTtlSecs: 120,
});
let projectMetadata = response.body.feeds[0];
if (projectMetadata == undefined) {
throw new coda.UserVisibleError("The table has no data to display!");
}
else {
let properties: coda.ObjectSchemaProperties = {};
let featuredProperties = [];
for (const [name, value] of Object.entries(projectMetadata)) {
if (name == "entry_id") {
properties[name] = {
type: coda.ValueType.Number
};
}
else {
properties[name] = {
type: coda.ValueType.String
};
}
featuredProperties.push(name);
}
let displayProperty = "created_at";
let idProperty = "entry_id";
// Return the schema for each row.
return coda.makeObjectSchema({
properties: properties,
displayProperty: displayProperty,
idProperty: idProperty,
featuredProperties: featuredProperties,
});
}
},
},
formula: {
name: "SyncChannelData",
description: "Read data from all fields in channel.",
parameters: [
common_parameters[0],
common_parameters[2],
common_parameters[3],
common_parameters[4],
common_parameters[5],
common_parameters[6],
common_parameters[7],
common_parameters[8],
common_parameters[9],
common_parameters[10],
common_parameters[11],
common_parameters[12],
common_parameters[13],
],
execute: async function ([ChannelId, results, days, start, end, offset, min, max, round, timescale, sum, average, median], context) {
let url_string = "https://api.thingspeak.com/channels/" + ChannelId + "/feeds.json?api_key=" + await getChannelAPI(ChannelId, context)
url_string = queryStringParameters(url_string, results, days, start, end, offset, min, max, round, timescale, sum, average, median)
let response = await context.fetcher.fetch({
method: "GET",
url: url_string,
cacheTtlSecs: 0,
});
let items = response.body.feeds;
if (items[0] != undefined) {
return {
result: items,
};
}
else {
throw new coda.UserVisibleError("The table has no data to display!");
}
}
}
})
// Sync table that displays data of a particular field of a channel
pack.addSyncTable({
name: "FieldData",
identityName: "FieldData",
schema: ChannelDataSchema,
dynamicOptions: {
getSchema: async function (context, _, { ChannelId, FieldId }) {
let url_string = "https://api.thingspeak.com/channels/" + ChannelId + "/fields/" + FieldId + ".json?api_key=" + await getChannelAPI(ChannelId, context)
let response = await context.fetcher.fetch({
method: "GET",
url: url_string,
cacheTtlSecs: 120
});
let projectMetadata = response.body.feeds[0];
if (projectMetadata == undefined) {
throw new coda.UserVisibleError("The table has no data to display!");
}
else {
let properties: coda.ObjectSchemaProperties = {};
let featuredProperties = [];
for (const [name, value] of Object.entries(projectMetadata)) {
if (name == "entry_id") {
properties[name] = {
type: coda.ValueType.Number
};
}
else {
properties[name] = {
type: coda.ValueType.String
};
}
featuredProperties.push(name);
}
let displayProperty = "created_at";
let idProperty = "entry_id";
// Return the schema for each row.
return coda.makeObjectSchema({
properties: properties,
displayProperty: displayProperty,
idProperty: idProperty,
featuredProperties: featuredProperties,
});
}
},
},
formula: {
name: "SyncFieldData",
description: "Read data from single field of channel.",
parameters: [
common_parameters[0],
common_parameters[1],
common_parameters[2],
common_parameters[3],
common_parameters[4],
common_parameters[5],
common_parameters[6],
common_parameters[7],
common_parameters[8],
common_parameters[9],
common_parameters[10],
common_parameters[11],
common_parameters[12],
common_parameters[13],
],
execute: async function ([ChannelId, FieldId, results, days, start, end, offset, min, max, round, timescale, sum, average, median], context) {
let url_string = "https://api.thingspeak.com/channels/" + ChannelId + "/fields/" + FieldId + ".json?api_key=" + await getChannelAPI(ChannelId, context)
url_string = queryStringParameters(url_string, results, days, start, end, offset, min, max, round, timescale, sum, average, median)
let response = await context.fetcher.fetch({
method: "GET",
url: url_string,
cacheTtlSecs: 0,
});
let items = response.body.feeds;
return {
result: items,
};
}
}
})
// Formula that creates and sends email alerts
pack.addFormula({
name: "CreateEmailAlert",
description: "Create an email alert",
resultType: coda.ValueType.String,
isAction: true,
parameters: [
coda.makeParameter({
type: coda.ParameterType.String,
name: "alert_api_key",
description: "Specify the alerts API key, which you can find in your profile (https://thingspeak.com/account/profile). \
This key is different from the channel API and user API keys.",
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "subject",
description: "Specify the subject for the email message, up to 60 characters.",
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "body_description",
description: "Specify the body of the email message, up to 500 characters.",
}),
],
execute: async function ([alert_api_key, subject, body_description], context) {
if (alert_api_key != undefined && subject != undefined && body_description != undefined) {
let response = await context.fetcher.fetch({
method: "POST",
headers: {
"Content-Type": "application/json",
"ThingSpeak-Alerts-API-Key": alert_api_key
},
url: "https://api.thingspeak.com/alerts/send",
body: JSON.stringify({
"subject": subject,
"body": body_description
})
});
if (response.status == 200) {
return "Updation successfull"
}
else {
return "Something went wrong!"
}
}
return "Waiting"
}
})
// Sync table that displays all the alerts processed
pack.addSyncTable({
name: "AlertHistory",
identityName: "AlertHistory",
schema: AlertHistorySchema,
formula: {
name: "SyncAlertHistory",
description: "List alerts history.",
parameters: [
coda.makeParameter({
type: coda.ParameterType.String,
name: "alert_api_key",
description: "Specify the alerts API key, which you can find in your profile (https://thingspeak.com/account/profile). \
This key is different from the channel API and user API keys.",
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "count",
description: "The number of results to return. The default value is 10, the maximum value is 100.",
optional: true
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "subject_contains",
description: "Include only history items with subject containing this value, sensitive to case.",
optional: true
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "status",
description: "Include only history items with status containing this value.",
optional: true
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "after",
description: "Include only history items with requested_at later than this time. Format times per ISO 8601. \
For example, 2020-05-15T20:03:48-05:00 represents May 15, 2020, 20:03:48 EST. \
If you do not include the time zone offset, ThingSpeak assumes the specified time is in UTC. \
Note: Alerts history items are retained for only 7 days, after which they are no longer available.",
optional: true
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "before",
description: "Include only history items with requested_at earlier than this time. Format times per ISO 8601. \
For example, 2020-05-15T20:03:48-05:00 represents May 15, 2020, 20:03:48 EST. \
If you do not include the time zone offset, ThingSpeak assumes the specified time is in UTC. \
Note: Alerts history items are retained for only 7 days, after which they are no longer available.",
optional: true
}),
],
execute: async function ([alert_api_key, count, subject_contains, status, after, before], context) {
let url_string = "https://api.thingspeak.com/alerts/history";
let added_initial_parameter = false
if (count != undefined) {
if (!added_initial_parameter) {
url_string += "?count=" + count
}
else {
url_string += "&count=" + count
}
}
if (subject_contains != undefined) {
if (!added_initial_parameter) {
url_string += "?subject_contains=" + subject_contains
added_initial_parameter = true
}
else {
url_string += "&subject_contains=" + count
}
}
if (status != undefined) {
if (!added_initial_parameter) {
url_string += "?status=" + status
added_initial_parameter = true
}
else {
url_string += "&status=" + status
}
}
if (after != undefined) {
if (!added_initial_parameter) {
url_string += "?after=" + after
added_initial_parameter = true
}
else {
url_string += "&after=" + after
}
}
if (before != undefined) {
if (!added_initial_parameter) {
url_string += "?before=" + before
added_initial_parameter = true
}
else {
url_string += "&before=" + before
}
}
let response = await context.fetcher.fetch({
method: "GET",
headers: {
"ThingSpeak-Alerts-API-Key": alert_api_key
},
url: url_string,
cacheTtlSecs: 0,
});
let items = response.body;
if (items[0] == undefined) {
throw new coda.UserVisibleError("The table has no data to display!");
}
else {
return {
result: items,
};
}
}
}
})
// Formula that creates a new channel
pack.addFormula({
name: "CreateChannel",
description: "Create a new channel.",
isAction: true,
resultType: coda.ValueType.String,
parameters: [
coda.makeParameter({
type: coda.ParameterType.String,
name: "name",
description: "Name of the channel.",
optional: true
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "description",
description: "Specify the description for the channel.",
optional: true
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "latitude",
description: "Latitude in degrees.",
optional: true
}),
coda.makeParameter({
type: coda.ParameterType.Number,
name: "longitude",
description: "Longitude in degrees.",
optional: true
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "public_flag",
description: "Whether the channel is public. The default is false.",
optional: true
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "metadata",
description: "Metadata for the channel, which can include JSON, XML, or any other data.",
optional: true
}),
coda.makeParameter({
type: coda.ParameterType.String,
name: "url",
description: "Web page URL for the channel.",
optional: true
}),
],
execute: async function ([name, description, latitude, longitude, public_flag, metadata, url], context) {
let invocationToken = context.invocationToken;
let user_api_key = "{{user_api_key-" + invocationToken + "}}";
let payload = {
"api_key": user_api_key,
};
if (name != undefined) {
payload["name"] = name
}
if (description != undefined) {
payload["description"] = description
}
if (url != undefined) {
payload["url"] = url
}
if (longitude != undefined) {
payload["longitude"] = String(longitude)
}
if (latitude != undefined) {
payload["latitude"] = String(latitude)
}
if (public_flag != undefined) {
payload["public_flag"] = public_flag
}
if (metadata != undefined) {
payload["metadata"] = metadata
}
let response = await context.fetcher.fetch({
method: "POST",
url: "https://api.thingspeak.com/channels.json",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
form: payload
});
if (response.status == 200) {
return "Channel Created!"
}
else if (response.status == 402) {
return "You have exceeded channel limit!"
}
else {
return "Something went wrong!"
}
}
})
// Formula that clears the data of a channel
pack.addFormula({
name: "ClearChannel",
description: "Clears all the data from a channel",
resultType: coda.ValueType.String,
isAction: true,
parameters: [
common_parameters[0],
],
execute: async function ([ChannelId], context) {
let invocationToken = context.invocationToken;
let user_api_key = "{{user_api_key-" + invocationToken + "}}";
if (ChannelId != undefined) {
let response = await context.fetcher.fetch({
method: "DELETE",
url: "https://api.thingspeak.com/channels/" + ChannelId + "/feeds.json",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
form: {
api_key: user_api_key
}
});
if (response.status == 200) {
return "Channel Cleared!"
}
else {
return "Something went wrong!"
}
}
else {
return "Waiting!"
}
}
})
// Formula that deletes a Channel
pack.addFormula({
name: "DeleteChannel",
description: "Delete a channel.",
resultType: coda.ValueType.String,
isAction: true,
parameters: [
common_parameters[0],
],
execute: async function ([ChannelId], context) {
let invocationToken = context.invocationToken;
let user_api_key = "{{user_api_key-" + invocationToken + "}}";
if (ChannelId != undefined) {
let response = await context.fetcher.fetch({
method: "DELETE",
url: "https://api.thingspeak.com/channels/" + ChannelId + ".json",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
form: {
api_key: user_api_key
}
});
if (response.status == 200) {
return "Channel Deleted!"
}
else {
return "Something went wrong!"
}
}
else {
return "Waiting!"
}
}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment