If someone could point me in the right direction getting the following sample code working as a scripting datasource in Mango 4, it would be appreciated. I have the need to connect to DegreeDays.net API so I can import a history of Heating Degree Days into a Mango Datapoint. Here is the following sample code from the DegreeDays.net API developer's page:
const crypto = require('crypto'), // built-in module, no need to npm install
fetch = require('node-fetch'); // install with npm install node-fetch
// The test API access keys are described at www.degreedays.net/api/test
// They will let you access data from the Cape Cod area only.
// To fetch data from locations worldwide, sign up for a proper API account at
// www.degreedays.net/api/ and copy your API access keys here.
const accountKey = 'test-test-test';
const securityKey = 'test-test-test-test-test-test-test-test-test-test-test-test-test';
// You can call the API over HTTP using http://apiv1.degreedays.net/json or
// over HTTPS using https://apiv1.degreedays.net/json - set the endpoint URL
// below as appropriate.
const endpoint = 'http://apiv1.degreedays.net/json';
// ************* STEP 1: Create the request ************************************
// First we create a JSON request that specifies what we want from the API.
// See www.degreedays.net/api/json#request for more on this.
// You can fetch data from a station ID, a longitude/latitude position, or a
// postal/zip code.
const location = {
type: 'PostalCodeLocation',
postalCode: '02532',
countryCode: 'US'
};
// In this example we fetch both HDD and CDD, using the same breakdown (daily
// data covering the last 7 days) for both. For more breakdown options see
// www.degreedays.net/api/json#breakdown
const breakdown = {
type: 'DailyBreakdown',
period: {
type: 'LatestValuesPeriod',
numberOfValues: 7
}
};
const locationDataRequest = {
type: 'LocationDataRequest',
location: location,
dataSpecs: {
// Here we specify 2 DataSpec items: one for HDD and one for CDD. You
// can specify up to 100 DataSpec items in one request (e.g. to fetch
// data in lots of base temperatures). With an API Standard+ account you
// can have a DataSpec for hourly temperature data too.
// Give each DataSpec a unique name so you can get the corresponding
// DataSet from the response.
myHDD: {
type: 'DatedDataSpec',
calculation: {
type: 'HeatingDegreeDaysCalculation',
baseTemperature: {
unit: 'F',
value: 60
}
},
breakdown: breakdown
},
myCDD: {
type: 'DatedDataSpec',
calculation: {
type: 'CoolingDegreeDaysCalculation',
baseTemperature: {
unit: 'F',
value: 70
}
},
breakdown: breakdown
}
}
};
const fullRequest = {
securityInfo: {
endpoint: endpoint,
accountKey: accountKey,
timestamp: new Date().toISOString(),
random: Buffer.from(crypto.randomBytes(12)).toString('hex')
},
request: locationDataRequest
};
const fullRequestJson = JSON.stringify(fullRequest);
// Now our JSON request is ready. Uncomment the line below to log the JSON:
//console.log(fullRequestJson);
// ************* STEP 2: Send the request to the API ***************************
// Next we sign the JSON request and package everything together into an HTTP
// request which we send to the Degree Days.net API. This follows the spec at
// www.degreedays.net/api/json#send
const signatureBytes =
crypto.createHmac('sha256', securityKey).update(fullRequestJson).digest();
// The API requires the JSON request and the signature to be base64url encoded.
function base64urlEncode(unencoded) {
return Buffer.from(unencoded).toString('base64')
.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
}
// Send the HTTP request to the API servers using node-fetch. You could change
// this to use another HTTP library if you wanted.
fetch(endpoint, {
method: 'POST',
body: 'request_encoding=base64url' +
'&signature_method=HmacSHA256' +
'&signature_encoding=base64url' +
'&encoded_request=' + base64urlEncode(fullRequestJson) +
'&encoded_signature=' + base64urlEncode(signatureBytes),
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
})
.then(response => {
if (!response.ok) {
throw new Error(response.status + ': ' + response.statusText);
}
return response.json();
})
.catch(err => console.error('Problem connecting to API:', err)
.then(parsedObject => handleResponse(parsedObject))
.catch(err => console.error('Problem handling API response:', err));
// ************* STEP 3: Process the response from the API *********************
// The JSON response is explained at www.degreedays.net/api/json#response
function handleResponse(fullResponse) {
// fullResponse.metadata has some rate limit info, but we are mainly
// interested in fullResponse.response (a LocationDataResponse in this case).
const response = fullResponse.response;
if (response.type === 'Failure') {
// See www.degreedays.net/api/json#failure for more about failures.
console.log('Request failure:', response);
} else {
// The response contains a lot of useful info, as shown in the JSON docs
// at www.degreedays.net/api/json#response
console.log('Station ID: ', response.stationId);
// "myHDD" is the name we gave the HDD DataSpec in our request.
const hddData = response.dataSets.myHDD;
if (hddData.type === 'Failure') {
console.log('Failure for HDD DataSet:', hddData);
} else {
console.log('HDD:');
for (var v of hddData.values) {
console.log(v.d + ': ' + v.v);
}
}
const cddData = response.dataSets.myCDD;
if (hddData.type === 'Failure') {
console.log('Failure for CDD DataSet:', cddData);
} else {
console.log('CDD:');
for (var v of cddData.values) {
console.log(v.d + ': ' + v.v);
}
}
}
}
I appreciate the help. Thanks.