Fetching from harmonie servers
This commit is contained in:
@@ -0,0 +1,73 @@
|
|||||||
|
package fetchDMI
|
||||||
|
|
||||||
|
import cats.effect._
|
||||||
|
import fs2.io.file.{Files, Path}
|
||||||
|
import org.http4s._
|
||||||
|
import org.http4s.client.Client
|
||||||
|
import org.http4s.ember.client.EmberClientBuilder
|
||||||
|
import org.typelevel.log4cats.Logger
|
||||||
|
import org.typelevel.log4cats.slf4j.Slf4jLogger
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime
|
||||||
|
|
||||||
|
|
||||||
|
final case class HarmonieServerConfig(
|
||||||
|
api_key: String,
|
||||||
|
url: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
object FetchService {
|
||||||
|
def of: IO[FetchService] = {
|
||||||
|
Slf4jLogger.create[IO].map(logger => new FetchService(logger))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FetchService(log: Logger[IO]) {
|
||||||
|
private val harmonieServerConfig: HarmonieServerConfig = (
|
||||||
|
sys.env.get("HARMONIE_EDR_API_KEY"),
|
||||||
|
sys.env.get("HARMONIE_EDR_URL"),
|
||||||
|
) match {
|
||||||
|
case (Some(api_key), Some(url)) =>
|
||||||
|
HarmonieServerConfig(api_key, url)
|
||||||
|
case _ =>
|
||||||
|
throw new RuntimeException("Unable to load harmonie config: Missing required environment variables")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
https://dmigw.govcloud.dk/v1/forecastedr/collections/harmonie_dini_sf/grib
|
||||||
|
?parameter-name=temperature-2m
|
||||||
|
&datetime=2025-01-28T00:00:00Z
|
||||||
|
&api-key=b12d36c7-d7ba-4dca-9bc9-de0c9c27435f
|
||||||
|
*/
|
||||||
|
|
||||||
|
private val baseUrl: IO[Uri] = IO(Uri.unsafeFromString(harmonieServerConfig.url))
|
||||||
|
private def makeRequest(client: Client[IO], url: Uri) = {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
def fetchFromDateTime(time: ZonedDateTime) = {
|
||||||
|
EmberClientBuilder.default[IO].build.use { client =>
|
||||||
|
for {
|
||||||
|
base <- baseUrl
|
||||||
|
queryParams = Query.fromPairs(
|
||||||
|
"parameter-name" -> "temperature-2m",
|
||||||
|
"datetime" -> time.toString,
|
||||||
|
"api-key" -> harmonieServerConfig.api_key,
|
||||||
|
)
|
||||||
|
urlWithParams = Uri.unsafeFromString(s"${base.toString}?${queryParams.toString}")
|
||||||
|
_ <- IO.println(urlWithParams)
|
||||||
|
|
||||||
|
request = Request[IO](Method.GET, urlWithParams)
|
||||||
|
|
||||||
|
_ <- Files[IO].createDirectories(Path("data"))
|
||||||
|
|
||||||
|
_ <- client.stream(request)
|
||||||
|
.flatMap(_.body)
|
||||||
|
.through(Files[IO].writeAll(Path("data/tmp.grib")))
|
||||||
|
.compile
|
||||||
|
.drain
|
||||||
|
} yield ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package fetchDMI;
|
||||||
|
|
||||||
|
import cats.effect.IO
|
||||||
|
import cats.effect.unsafe.implicits.global
|
||||||
|
|
||||||
|
import java.time.{ZoneOffset, ZonedDateTime}
|
||||||
|
|
||||||
|
object FetchServiceTest {
|
||||||
|
def main(args: Array[String]): Unit = {
|
||||||
|
val program = for {
|
||||||
|
nowUTC <- IO(ZonedDateTime.now(ZoneOffset.UTC))
|
||||||
|
referenceTime = FileName.getClosestReferenceTime(nowUTC)
|
||||||
|
fetch <- FetchService.of
|
||||||
|
_ <- fetch.fetchFromDateTime(referenceTime)
|
||||||
|
} yield ()
|
||||||
|
|
||||||
|
program.unsafeRunSync()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package fetchDMI
|
||||||
|
|
||||||
|
import java.time.{ZoneOffset, ZonedDateTime}
|
||||||
|
|
||||||
|
object FileName {
|
||||||
|
def main(args: Array[String]): Unit = {
|
||||||
|
println("-------- FileName")
|
||||||
|
|
||||||
|
val nowUTC = ZonedDateTime.now(ZoneOffset.UTC)
|
||||||
|
val referenceTime = getClosestReferenceTime(nowUTC)
|
||||||
|
val timeList = generateTimeList(referenceTime)
|
||||||
|
|
||||||
|
timeList.foreach(println)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
def getClosestReferenceTime(time: ZonedDateTime): ZonedDateTime = {
|
||||||
|
val referenceHours = Vector(0, 3, 6, 9, 12, 15, 18, 21)
|
||||||
|
val currentHour = time.getHour
|
||||||
|
val closestHour = referenceHours
|
||||||
|
.filter(h => h <= currentHour)
|
||||||
|
.maxOption
|
||||||
|
.getOrElse(21) // actually should not be such case
|
||||||
|
|
||||||
|
time
|
||||||
|
.withHour(closestHour)
|
||||||
|
.withMinute(0)
|
||||||
|
.withSecond(0)
|
||||||
|
.withNano(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO make default count to 62 or 60
|
||||||
|
def generateTimeList(initialTime: ZonedDateTime, interval: Int = 1, count: Int = 5): List[ZonedDateTime] = {
|
||||||
|
(0 until count).map(id => initialTime.plusHours(id * interval)).toList
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user