-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: initiated calculation of CropSAR
- Loading branch information
1 parent
60b6ba1
commit dea3fab
Showing
3 changed files
with
149 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import * as functions from 'firebase-functions'; | ||
import { getPremiumUsers, getVineyard, getVineyardActions, getVineyards } from '../services/utils.service'; | ||
import { Vineyard } from '../models/vineyard.model'; | ||
import * as moment from 'moment/moment'; | ||
import { Action } from '../models/action.model'; | ||
import { executeGraphSync } from '../services/openeo.service'; | ||
|
||
const createGraph = (polygon: any, start: string, end: string) => { | ||
return { | ||
cropsar: { | ||
process_id: 'CropSAR', | ||
arguments: { | ||
biopar_type: 'ndvi', | ||
date: [start, end], | ||
polygon, | ||
}, | ||
namespace: 'vito', | ||
}, | ||
save: { | ||
process_id: 'save_result', | ||
arguments: { | ||
data: { | ||
from_node: 'cropsar', | ||
}, | ||
format: 'JSON', | ||
}, | ||
result: true, | ||
}, | ||
}; | ||
}; | ||
const calculateCropSAR = async (polygon: any, start: string, end: string) => { | ||
try { | ||
console.log(`Calculating CropSAR for polgyon with start ${start} and end ${end}`); | ||
const graph = createGraph(polygon, start, end); | ||
const result = await executeGraphSync(graph, 'json'); | ||
console.log(result); | ||
} catch (e) { | ||
console.error(`Could not calculate CropSAR`, e); | ||
} | ||
}; | ||
export const getCropSARDates = (actions: Action[]): [string, string] | undefined => { | ||
const dates = actions | ||
.map((a: Action) => moment(a.date).year()) | ||
.filter((year: number, index: number, years: number[]) => years.indexOf(year) === index) | ||
.sort(); | ||
if (dates.length > 0) { | ||
return [`${dates[0]}-01-01`, `${dates[dates.length - 1]}-12-31`]; | ||
} else { | ||
return undefined; | ||
} | ||
}; | ||
|
||
const calculateAllCropSAR = async () => { | ||
console.log('Starting calculation of CropSAR'); | ||
|
||
const users: string[] = await getPremiumUsers(); | ||
console.log(`Found ${users.length} users to process`); | ||
|
||
for (const uid of users) { | ||
const vineyards: string[] = await getVineyards(uid); | ||
console.log(`Found ${vineyards.length} vineyards for user ${uid}`); | ||
|
||
for (const id of vineyards) { | ||
try { | ||
const v: Vineyard = await getVineyard(uid, id); | ||
const actions = await getVineyardActions(uid, id); | ||
const dates = getCropSARDates(actions); | ||
|
||
if (dates) { | ||
await calculateCropSAR(v.location, dates[0], dates[1]); | ||
} else { | ||
console.warn(`No dates found for calculating CropSAR for vineyard ${v.id}`); | ||
} | ||
} catch (error) { | ||
console.error(`Error processing vineyard ${id} of ${uid}`, error); | ||
} | ||
} | ||
} | ||
}; | ||
|
||
export const cropsarPubsub = functions.pubsub.schedule('0 1 * * *').onRun(async () => { | ||
return calculateAllCropSAR(); | ||
}); | ||
export const cropsarHook = functions.https.onRequest(async () => { | ||
return calculateAllCropSAR(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
const OPENEO_URL = process.env.OPENEO_URL || ''; | ||
const OPENEO_USER = process.env.OPENEO_USER || ''; | ||
const OPENEO_PASSWORD = process.env.OPENEO_PASSWORD || ''; | ||
|
||
let AUTH_TOKEN: string; | ||
|
||
const authenticate = async (username: string, password: string): Promise<string> => { | ||
try { | ||
const response: any = await fetch(`${OPENEO_URL}/credentials/basic`, { | ||
headers: { | ||
Authorization: 'Basic ' + Buffer.from(username + ':' + password).toString('base64'), | ||
}, | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error(await response.text()); | ||
} | ||
const data = await response.json(); | ||
return `basic//${data.access_token}`; | ||
} catch (e) { | ||
console.error('Could not authenticate with OpenEO', e); | ||
throw new Error('Could not authenticate with OpenEO service'); | ||
} | ||
}; | ||
|
||
const getToken = async (): Promise<string> => { | ||
if (!AUTH_TOKEN) { | ||
AUTH_TOKEN = await authenticate(OPENEO_USER, OPENEO_PASSWORD); | ||
} | ||
return AUTH_TOKEN; | ||
}; | ||
|
||
const getHeaders = async (): Promise<any> => { | ||
const token = await getToken(); | ||
return { | ||
Authorization: `Bearer ${token}`, | ||
'Content-Type': 'application/json', | ||
}; | ||
}; | ||
export const executeGraphSync = async (graph: any, format: string): Promise<string> => { | ||
const response = await fetch(`${OPENEO_URL}/result`, { | ||
method: 'POST', | ||
headers: await getHeaders(), | ||
body: JSON.stringify({ | ||
log_level: 'debug', | ||
process: { | ||
process_graph: graph, | ||
}, | ||
}), | ||
}); | ||
if (!response.ok) { | ||
throw new Error(await response.text()); | ||
} | ||
|
||
if (format === 'json') { | ||
return response.json(); | ||
} else { | ||
throw new Error(`Unknown output format ${format}`); | ||
} | ||
}; |