Skip to content

Commit

Permalink
Add temperature factor
Browse files Browse the repository at this point in the history
  • Loading branch information
MergHQ committed Oct 7, 2020
1 parent 7efabc4 commit feb2d2e
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 32 deletions.
4 changes: 4 additions & 0 deletions bagbeer-deploy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ const deployment = new k8s.apps.v1.Deployment('bagbeer-service', {
{
name: 'AGRO_API_TOKEN',
valueFrom: getSecretRef('AGRO_API_TOKEN')
},
{
name: 'DARKSKY_TOKEN',
valueFrom: getSecretRef('DARKSKY_TOKEN')
}
]
}
Expand Down
24 changes: 17 additions & 7 deletions frontend/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import React, { useState } from 'react'
import additionalInfo from '../fixtures/statusAdditionalInfo'
import format from 'date-fns/format'
import { getCurrentStatus } from '../services/statusService'
import { useEffect } from 'react'

type BagBeerStatusProps = {
updated: Date,
status: string,
details: {
groundMoisture: number,
windSpeed: number
windSpeed: number,
groundMoistureUpdated: Date,
temp: number
}
update: () => void
}
Expand All @@ -20,20 +21,26 @@ type Props = {
status: string
details: {
groundMoisture: number,
windSpeed: number
windSpeed: number,
groundMoistureUpdated: Date,
temp: number
}
} | string
}

type DataContainerProps = {
groundMoisture: number,
windSpeed: number
windSpeed: number,
groundMoistureUpdated: Date,
temp: number
}

const DataContainer = (props: DataContainerProps) =>
<div className="data-container">
<p className="data-text">Ground moist. updated: {format(new Date(props.groundMoistureUpdated), 'd.M.yyyy kk:mm')}</p>
<p className="data-text">Ground moisture: {props.groundMoisture}m3/m3</p>
<p className="data-text">Wind speed: {props.windSpeed}m/s</p>
<p className="data-text">Temperature: {props.temp}°C</p>
</div>

const StatusContainer = (props: BagBeerStatusProps) => {
Expand All @@ -44,7 +51,12 @@ const StatusContainer = (props: BagBeerStatusProps) => {
<h2 className="additional-info">{additionalInfo[props.status]}</h2>
<button className="data-button" onClick={() => setDataContainerOpen(!dataContainerOpen)}>?</button>
{dataContainerOpen &&
<DataContainer groundMoisture={props.details.groundMoisture} windSpeed={props.details.windSpeed} />}
<DataContainer
groundMoisture={props.details.groundMoisture}
windSpeed={props.details.windSpeed}
groundMoistureUpdated={props.details.groundMoistureUpdated}
temp={props.details.temp}
/>}
<p>{format(new Date(props.updated), 'd.M.yyyy kk:mm')}</p>
<button className="update-button" onClick={props.update}>Update</button>
</div>
Expand Down Expand Up @@ -76,6 +88,4 @@ const App = (props: Props) => {
)
}



export default App
4 changes: 3 additions & 1 deletion frontend/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ export type InitialProps = {
status: string,
details: {
groundMoisture: number,
windSpeed: number
windSpeed: number,
groundMoistureUpdated: Date,
temp: number
}
} | string
}
Expand Down
22 changes: 19 additions & 3 deletions service/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
import { Application } from 'https://deno.land/x/abc/mod.ts'
import { logger } from 'https://deno.land/x/abc/middleware/logger.ts'
import { CORSConfig, cors } from 'https://deno.land/x/abc/middleware/cors.ts'
import { cors } from 'https://deno.land/x/abc/middleware/cors.ts'
import maybe from 'https://raw.githubusercontent.com/MergHQ/denofun/maybe-get-or-else/lib/maybe.ts'
import { fetchCurrentStatus } from './service/agro.ts'
import { fetchCurrentData } from './service/agro.ts'
import { fetchCached } from './service/darksky.ts'
import resolveStatus from './resolvers/statusResolver.ts'

if (!Deno.env.get('POLY_ID') || !Deno.env.get('AGRO_API_TOKEN') || !Deno.env.get('DARKSKY_TOKEN')) {
console.error('Missing env vars.')
Deno.exit(1)
}

const app = new Application()

app
.use(logger())
.use(cors())
.get('/api/status', ctx =>
fetchCurrentStatus()
Promise.all([fetchCurrentData(), fetchCached()])
.then(([{ updated, details }, { temp, updated: tempUpdated }]) => ({
updated: tempUpdated,
status: resolveStatus(details.groundMoisture, details.windSpeed, temp),
details: {
...details,
temp,
groundMoistureUpdated: updated
}
}))
.then(status => ctx.json(status))
.catch(e => ctx.json(e, e.status)))
.get('/health', ctx => ctx.json({ ok: true }))
Expand Down
11 changes: 9 additions & 2 deletions service/src/resolvers/statusResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ const moistureFactorMultiplier = 1.5

const limitFactor = curry(Math.min)(scale.length - 1)

const resolveStatus = (soilMoisture: number, windSpeed: number) => {
const resolveStatus = (soilMoisture: number, windSpeed: number, temp: number) => {
const moistureFactor = (soilMoisture / (moistureLimit / 2)) * moistureFactorMultiplier
const windFactor = windSpeed / (windLimit / 2)
const temperaturFactor =
temp < 5 ? 3 :
temp < 10 ? 2 :
temp < 15 ? 1.5 :
temp < 20 ? 1 :
temp < 25 ? 0 : 0

const index = pipe(
() => (moistureFactor + windFactor) - 1,
() => (moistureFactor + windFactor + temperaturFactor) - 1,
Math.round,
limitFactor
)
Expand Down
25 changes: 6 additions & 19 deletions service/src/service/agro.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
import maybe, { Maybe } from 'https://raw.githubusercontent.com/MergHQ/denofun/maybe-get-or-else/lib/maybe.ts'
import memoize from 'https://raw.githubusercontent.com/MergHQ/denofun/memoize-ttl/lib/memoize.ts'
import { checkError } from '../error.ts'
import resolveStatus from '../resolvers/statusResolver.ts'

const baseUrl = 'http://api.agromonitoring.com/agro/1.0'
const buildUrlString = (polyId: Maybe<string> , appId: Maybe<string>) => (resource: string) => {
const resolvedPolygonId =
polyId
.map(p => `polyid=${p}`)
.getOrElse('')
const buildUrlString = (polyId: string , appId: string) => (resource: string) =>
`${baseUrl}/${resource}?polyid=${polyId}&appid=${appId}`

const resolvedAppId =
appId
.map(a => `appid=${a}`)
.getOrElse('')

return `${baseUrl}/${resource}?${resolvedPolygonId}&${resolvedAppId}`
}
const cacheTTL = 60000

const withIdentifiers = buildUrlString(maybe(Deno.env.get('POLY_ID')), maybe(Deno.env.get('AGRO_API_TOKEN')))
const withResource = buildUrlString(Deno.env.get('POLY_ID')!, Deno.env.get('AGRO_API_TOKEN')!)

interface SoilApiResponse {
dt: number,
Expand All @@ -44,23 +32,22 @@ const parseSoilResult = ({ dt, t10, moisture, t0 }: SoilApiResponse): SoilMoistu
})

const fetchSoilMoisture = () =>
fetch(withIdentifiers('soil'))
fetch(withResource('soil'))
.then(checkError)
.then((data: SoilApiResponse) => parseSoilResult(data))

const fetchWindSpeed = () =>
fetch(withIdentifiers('weather'))
fetch(withResource('weather'))
.then(checkError)
.then(({ wind }: WeatherApiResponse) => wind.speed)

const cachedSoilMoisture = memoize(fetchSoilMoisture, cacheTTL)
const cachedWindSpeed = memoize(fetchWindSpeed, cacheTTL)

export const fetchCurrentStatus = () =>
export const fetchCurrentData = () =>
Promise.all([cachedSoilMoisture(), cachedWindSpeed()])
.then(([moistureData, windSpeed]) => ({
updated: new Date(moistureData.dt),
status: resolveStatus(moistureData.moisture, windSpeed),
details: {
groundMoisture: moistureData.moisture,
windSpeed
Expand Down
25 changes: 25 additions & 0 deletions service/src/service/darksky.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import memoize from 'https://raw.githubusercontent.com/MergHQ/denofun/memoize-ttl/lib/memoize.ts'
import { checkError } from '../error.ts'

const hki = '60.169940,24.938679'
const chaceTTL = 120000
const url = `https://api.darksky.net/forecast/${Deno.env.get('DARKSKY_TOKEN')!}/${hki}?units=si`

interface DarkSkyResponse {
currently: {
time: number,
temperature: number
}
}

const fetchTemp = (): Promise<{ temp: number, updated: Date }> =>
fetch(url)
.then(checkError)
.then((data: DarkSkyResponse) => ({
updated: new Date(data.currently.time * 1000),
temp: data.currently.temperature
}))

const cached = memoize(fetchTemp, chaceTTL)

export const fetchCached = cached

1 comment on commit feb2d2e

@vercel
Copy link

@vercel vercel bot commented on feb2d2e Oct 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.