Okay, I decided to jump in and have some fun too a couple of days ago. I made a ton of changes and forgot to post yesterday. I do have more changes coming though after a few days to make more things generic.
I have not given permission yet for the script to access the spreadsheet, so am just returning data. Consequently, this is how I have the spreadsheet set up:
Cell |
Contents |
Cell |
Contents |
A1 |
API Key: |
B1 |
[my-api-key] |
A2 |
Person ID: |
B2 |
=GetPersonId(fetchApiKey()) |
A4 |
=GetRachioZoneSettings() |
|
|
function fetchAPIKey() {
// Setup the sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
//var sheets = ss.getSheets();
var sheet = ss.getActiveSheet();
var range = sheet.getRange('B1');
var value = range.getValue();
Logger.log(value);
return (value);
}
function GetPersonID(Key) {
// Setup the sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
//var sheets = ss.getSheets();
var sheet = ss.getActiveSheet();
var range = sheet.getRange('B2');
//var value = range.getValue();
//if (value == "") {
var url = "https://api.rach.io/1/public/person/info";
var headers = {
"contentType": "application/json",
"headers": {"Authorization": "Bearer " + Key}
};
var response = UrlFetchApp.fetch(url, headers);
var PersonID = JSON.parse(response.getContentText());
value = PersonID.id;
//range.setValue(value)
//}
return (value)
}
function length(obj) {
return (Object.keys(obj).length);
}
function FROM_UNIX_EPOCH(epoch_in_ms, timeZone) {
if ((typeof epoch_in_ms != "number") || (epoch_in_ms == 0)) {
return (epoch_in_ms);
}
var date = new Date(epoch_in_ms);
return (Utilities.formatDate(date, timeZone, "dd-MMM-yyyy HH:mm:ss"));
}
function GetRachioZoneSettings() {
// Setup the sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
//var sheets = ss.getSheets();
var sheet = ss.getActiveSheet();
var APIKey = fetchAPIKey();
var PersonID = GetPersonID(APIKey);
// get Device(s) information this person has access to
var url = "https://api.rach.io/1/public/person/" + PersonID;
var headers = {
"contentType": "application/json",
"headers": {"Authorization": "Bearer " + APIKey}
};
var response = UrlFetchApp.fetch(url, headers);
var dataSet = JSON.parse(response.getContentText());
var DeviceCount = length(dataSet.devices);
Logger.log("devices = %s", DeviceCount);
var rows = [];
var RowNum = 0;
// Do the headers first so we know the data
var showDisabled = true;
rows[RowNum] = new Array();
rows[RowNum++] = ["Person", "->", "->", "->", "->", "->"];
rows[RowNum] = new Array();
rows[RowNum++] = ["ID", "Username", "FullName", "Email", "CreateDate (UTC)", "Deleted"];
rows[RowNum] = new Array();
var n = 0;
rows[RowNum][n++] = dataSet.id;
rows[RowNum][n++] = dataSet.username;
rows[RowNum][n++] = dataSet.fullName;
rows[RowNum][n++] = dataSet.email;
//rows[RowNum][n++] = dataSet.createDate;
rows[RowNum][n++] = FROM_UNIX_EPOCH(dataSet.createDate, "+0000");
rows[RowNum][n++] = dataSet.deleted;
RowNum++;
// Empty Row
rows[RowNum++] = new Array();
// Iterate on each Rachio device
rows[RowNum] = new Array();
rows[RowNum++] = ["Device", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->"];
rows[RowNum] = new Array();
rows[RowNum++] = ["#", "Name", "CreateDate", "ID", "Status", "TimeZone", "Latitude", "Longitude", "SerialNumber", "RainDelayExpirationDate",
"MacAddress", "On", "Model", "ScheduleModeType", "Deleted", "RainSensorTripped", "HomeKitComatible", "UtcOffset"];
for (ii = 0; ii < DeviceCount; ii++) {
rows[RowNum] = new Array();
var n = 0;
rows[RowNum][n++] = ii + 1; // Device number
rows[RowNum][n++] = dataSet.devices[ii].name;
//rows[RowNum][n++] = dataSet.devices[ii].createDate;
rows[RowNum][n++] = FROM_UNIX_EPOCH(dataSet.devices[ii].createDate, dataSet.devices[ii].timeZone);
rows[RowNum][n++] = dataSet.devices[ii].id;
rows[RowNum][n++] = dataSet.devices[ii].status;
rows[RowNum][n++] = dataSet.devices[ii].timeZone;
rows[RowNum][n++] = dataSet.devices[ii].latitude;
rows[RowNum][n++] = dataSet.devices[ii].longitude;
rows[RowNum][n++] = dataSet.devices[ii].serialNumber;
//rows[RowNum][n++] = dataSet.devices[ii].rainDelayExpirationDate;
rows[RowNum][n++] = FROM_UNIX_EPOCH(dataSet.devices[ii].rainDelayExpirationDate, dataSet.devices[ii].timeZone);
rows[RowNum][n++] = dataSet.devices[ii].macAddress;
rows[RowNum][n++] = dataSet.devices[ii].on;
rows[RowNum][n++] = dataSet.devices[ii].model;
rows[RowNum][n++] = dataSet.devices[ii].scheduleModeType;
rows[RowNum][n++] = dataSet.devices[ii].deleted;
rows[RowNum][n++] = dataSet.devices[ii].rainSensorTripped;
rows[RowNum][n++] = dataSet.devices[ii].homeKitCompatible;
rows[RowNum][n++] = dataSet.devices[ii].utcOffset;
RowNum++;
}
// Empty Row
rows[RowNum++] = new Array();
// Iterate on each Rachio device for each zone
rows[RowNum] = new Array();
rows[RowNum++] = ["Device",
"Zone", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->",
"Nozzle", "->", "Soil", "Slope", "->", "Crop", "->", "Shade", "WateringAdjustment", "->", "->", "->", "->"];
rows[RowNum] = new Array();
rows[RowNum++] = ["#",
"ZoneNumber", "Name", "ID", "Enabled", "AvailableWater", "RootZoneDepth", "ManagementAllowedDepletion", "Efficiency",
"YardAreaSquareFeet", "ImageUrl", "LastWateredDate", "ScheduleDataModified", "FixedRunTime", "SaturatedDepthOfWater",
"DepthOfWater", "MaxRuntime", "RuntimeNoMultiplier", "Runtime",
"Name", "Inches per Hour", "Name", "Name", "SortOrder", "Name", "Coefficient", "Name", "1", "2", "3", "4", "5"];
for (ii = 0; ii < DeviceCount; ii++) {
var Zones = length(dataSet.devices[ii].zones);
// iterate on the zones in each Rachio device for this account
for (jj = 0; jj < Zones; jj++) {
// only output to the spreadsheet zones that are enabled
if ((dataSet.devices[ii].zones[jj].enabled == true) || showDisabled) {
rows[RowNum] = new Array();
var n = 0;
rows[RowNum][n++] = ii + 1; // Device number
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].zoneNumber;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].name;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].id;
if (showDisabled) {
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].enabled;
}
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].availableWater;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].rootZoneDepth;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].managementAllowedDepletion;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].efficiency;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].yardAreaSquareFeet;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].imageUrl;
//rows[RowNum][n++] = dataSet.devices[ii].zones[jj].lastWateredDate;
rows[RowNum][n++] = FROM_UNIX_EPOCH(dataSet.devices[ii].zones[jj].lastWateredDate, dataSet.devices[ii].timeZone);
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].scheduleDataModified
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].fixedRuntime;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].saturatedDepthOfWater;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].depthOfWater;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].maxRuntime;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].runtimeNoMultiplier;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].runtime;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].customNozzle.name;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].customNozzle.inchesPerHour;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].customSoil.name;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].customSlope.name;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].customSlope.sortOrder;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].customCrop.name;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].customCrop.coefficient;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].customShade.name;
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].wateringAdjustmentRuntimes["1"];
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].wateringAdjustmentRuntimes["2"];
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].wateringAdjustmentRuntimes["3"];
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].wateringAdjustmentRuntimes["4"];
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].wateringAdjustmentRuntimes["5"];
rows[RowNum][n++] = dataSet.devices[ii].zones[jj].wateringAdjustmentRuntimes["6"];
RowNum++;
}
}
}
// Empty Row
rows[RowNum++] = new Array();
// Iterate on each Rachio device for each schedule rule
rows[RowNum] = new Array();
rows[RowNum++] = ["Device",
"ScheduleRule"];
rows[RowNum] = new Array();
rows[RowNum++] = ["#"];
for (ii = 0; ii < DeviceCount; ii++) {
var rules = length(dataSet.devices[ii].scheduleRules);
//iterate on the zones in each Rachio device for this account
for (jj = 0; jj < rules; jj++) {
rows[RowNum] = new Array();
var n = 0;
rows[RowNum][n++] = ii + 1; // Device number
RowNum++;
}
}
// Empty Row
rows[RowNum++] = new Array();
// Iterate on each Rachio device for each Flex schedule rule
rows[RowNum] = new Array();
rows[RowNum++] = ["Device",
"FlexScheduleRule", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->", "->"];
rows[RowNum] = new Array();
rows[RowNum++] = ["#",
"#", "ID", "Operator", "Summary", "CycleSoak", "StartDate", "Name", "Ennabled", "StartDay", "StartMonth", "StartYear",
"StartHour", "StartMinute", "TotalDuration", "ExternalName", "Type"];
for (ii = 0; ii < DeviceCount; ii++) {
var rules = length(dataSet.devices[ii].flexScheduleRules);
//iterate on the zones in each Rachio device for this account
for (jj = 0; jj < rules; jj++) {
rows[RowNum] = new Array();
var n = 0;
rows[RowNum][n++] = ii + 1; // Device number
rows[RowNum][n++] = jj + 1; // Flex Schedule Rule number
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].id;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].operator
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].summary;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].cycleSoak;
//rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].startDate;
rows[RowNum][n++] = FROM_UNIX_EPOCH(dataSet.devices[ii].flexScheduleRules[jj].startDate, dataSet.devices[ii].timeZone);
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].name;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].enabled;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].startDay;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].startMonth;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].startYear;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].startHour;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].startMinute;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].totalDuration;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].externalName;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].type;
RowNum++;
}
}
// Empty Row
rows[RowNum++] = new Array();
// Iterate on each Rachio device for each Flex schedule rule's scheduleJobTypes
rows[RowNum] = new Array();
rows[RowNum++] = ["Device",
"FlexScheduleRule",
"ScheduleJobTypes"];
rows[RowNum] = new Array();
rows[RowNum++] = ["#",
"#", "ID", "Operator", "Summary", "CycleSoak", "StartDate", "Name", "Ennabled", "StartDay", "StartMonth", "StartYear",
"StartHour", "StartMinute", "TotalDuration", "ExternalName", "Type"];
for (ii = 0; ii < DeviceCount; ii++) {
var rules = length(dataSet.devices[ii].flexScheduleRules);
//iterate on the zones in each Rachio device for this account
for (jj = 0; jj < rules; jj++) {
rows[RowNum] = new Array();
var n = 0;
rows[RowNum][n++] = ii + 1; // Device number
rows[RowNum][n++] = jj + 1; // Flex Schedule Rule number
var types = length(dataSet.devices[ii].flexScheduleRules[jj].scheduleJobTypes);
for (kk = 0; kk < types; kk++) {
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].scheduleJobTypes[kk];
}
RowNum++;
}
}
// Empty Row
rows[RowNum++] = new Array();
// Iterate on each Rachio device for each Flex schedule rule's zones
rows[RowNum] = new Array();
rows[RowNum++] = ["Device",
"FlexScheduleRule",
"Zone", "->", "->"];
rows[RowNum] = new Array();
rows[RowNum++] = ["#",
"#",
"ID", "SortOrder", "Duration (secs)"];
for (ii = 0; ii < DeviceCount; ii++) {
var rules = length(dataSet.devices[ii].flexScheduleRules);
//iterate on the zones in each Rachio device for this account
for (jj = 0; jj < rules; jj++) {
var zones = length(dataSet.devices[ii].flexScheduleRules[jj].zones);
for (kk = 0; kk < zones; kk++) {
rows[RowNum] = new Array();
var n = 0;
rows[RowNum][n++] = ii + 1; // Device number
rows[RowNum][n++] = jj + 1; // Flex Schedule Rule number
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].zones[kk].zoneId;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].zones[kk].sortOrder;
rows[RowNum][n++] = dataSet.devices[ii].flexScheduleRules[jj].zones[kk].duration / 60.0;
RowNum++;
}
}
}
//destinationRange = sheet.getRange(20, 1, 20 + RowNum, n);
//destinationRange.setValues(rows);
return (rows);
}