Skip to content

Commit

Permalink
iss #24: [wip] devices config
Browse files Browse the repository at this point in the history
  • Loading branch information
maizy committed Jan 23, 2017
1 parent d0db1d9 commit 654fb7d
Show file tree
Hide file tree
Showing 20 changed files with 169 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import com.typesafe.scalalogging.LazyLogging
import scalikejdbc._
import ru.maizy.ambient7.analysis.AppOptions
import ru.maizy.ambient7.analysis.service.InfluxDbCo2Service
import ru.maizy.ambient7.core.data.Co2AgentId
import ru.maizy.ambient7.core.data.Co2Agent
import ru.maizy.ambient7.core.util.Dates.dateTimeForUser
import ru.maizy.ambient7.rdbms.Co2Service
import ru.maizy.influxdbclient.{ InfluxDbClient, InfluxDbConnectionSettings }
Expand All @@ -28,7 +28,7 @@ object AggregateCo2Command extends LazyLogging {

val now = ZonedDateTime.now()
// val now = ZonedDateTime.of(2015, 12, 3, 7, 12, 13, 14, ZoneOffset.UTC)
val agentId = Co2AgentId(opts.influxDbAgentName, opts.influxDbTags)
val agentId = Co2Agent(opts.influxDbAgentName, opts.influxDbTags)

val eitherDbStartDate = Co2Service.detectStartDateTime(agentId)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import scala.annotation.tailrec
import scala.collection.immutable.ListMap
import scala.util.{ Failure, Success }
import com.typesafe.scalalogging.LazyLogging
import ru.maizy.ambient7.core.data.{ Co2AggregatedLevels, Co2AgentId }
import ru.maizy.ambient7.core.data.{ Co2AggregatedLevels, Co2Agent }
import ru.maizy.influxdbclient.data.{ NullValue, SeriesItem, StringValue }
import ru.maizy.influxdbclient.util.Dates
import ru.maizy.influxdbclient.util.Escape.{ escapeValue, tagsToQueryCondition }
Expand All @@ -30,7 +30,7 @@ object InfluxDbCo2Service extends LazyLogging {
influxDbClient: InfluxDbClient,
from: ZonedDateTime,
until: ZonedDateTime,
agentId: Co2AgentId): Either[String, Co2AggregatedLevels] = {
agentId: Co2Agent): Either[String, Co2AggregatedLevels] = {

require(from.compareTo(until) < 0)

Expand Down Expand Up @@ -86,7 +86,7 @@ object InfluxDbCo2Service extends LazyLogging {
def detectStartDateTime(
influxDbClient: InfluxDbClient,
until: ZonedDateTime,
agentId: Co2AgentId,
agentId: Co2Agent,
maxEmptyDuration: Int = DEFAULT_MAX_EMPTY_DURATION): Either[String, ZonedDateTime] = {

val tagsConditions = tagsToQueryCondition(agentId.tags.asPairs)
Expand Down Expand Up @@ -162,7 +162,7 @@ object InfluxDbCo2Service extends LazyLogging {
startDate: ZonedDateTime,
until: ZonedDateTime,
influxDbClient: InfluxDbClient,
agentId: Co2AgentId): Map[ZonedDateTime, Co2AggregatedLevels] = {
agentId: Co2Agent): Map[ZonedDateTime, Co2AggregatedLevels] = {

@tailrec
def iter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package ru.maizy.ambient7.webapp

import java.time.ZoneId
import ru.maizy.ambient7.core.config.Defaults
import ru.maizy.ambient7.webapp.data.Co2Device
import ru.maizy.ambient7.core.data.Co2Device

case class AppConfig(
// FIXME: migrate to uni config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ import scala.collection.immutable.ListMap
import scala.util.{ Failure, Success, Try }
import com.typesafe.scalalogging.LazyLogging
import com.typesafe.config.{ Config, ConfigFactory }
import ru.maizy.ambient7.core.data.{ AgentTags, Co2AgentId }
import ru.maizy.ambient7.core.data.{ AgentTags, Co2Agent, Co2Device }
import ru.maizy.ambient7.webapp.AppConfig
import ru.maizy.ambient7.webapp.data.Co2Device


// TODO: safe config parsing with readable errors
Expand Down Expand Up @@ -59,7 +58,7 @@ trait AppConfigInit extends LazyLogging {
case Left(error) =>
throw new RuntimeException(s"Unable to parse agent-tags '$tagsString' for id=$id, skipping tags: $error")
}
Seq(id -> Co2Device(id, agentId = Co2AgentId(deviceConfig.getString("agent-name"), tags)))
Seq(id -> Co2Device(id, agent = Co2Agent(deviceConfig.getString("agent-name"), tags)))
}

appConfig.copy(co2Devices = ListMap(devicesList: _*))
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ package ru.maizy.ambient7.webapp.json
* See LICENSE.txt for details.
*/

import ru.maizy.ambient7.core.json.{ BaseProtocol, Co2AgentIdProtocol }
import ru.maizy.ambient7.webapp.data.Co2Device
import ru.maizy.ambient7.core.data.Co2Device
import ru.maizy.ambient7.core.json.{ BaseProtocol, Co2AgentProtocol }

trait Co2DeviceProtocol extends BaseProtocol with Co2AgentIdProtocol {
trait Co2DeviceProtocol extends BaseProtocol with Co2AgentProtocol {
implicit val deviceFormat = jsonFormat(Co2Device, "id", "agent")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ package ru.maizy.ambient7.webapp.servlet
import java.time.ZonedDateTime
import scalikejdbc._
import spray.json.{ JsNumber, JsObject, JsString, JsValue, pimpAny }
import ru.maizy.ambient7.core.data.Co2Device
import ru.maizy.ambient7.rdbms.Co2Service
import ru.maizy.ambient7.webapp.data.Co2Device
import ru.maizy.ambient7.webapp.servlet.helper.{ AppConfigSupport, DateParamsSupport, DeviceParamSupport }
import ru.maizy.ambient7.webapp.servlet.helper.{ PrimitiveParamsSupport, SprayJsonSupport, TimeZoneSupport }
import ru.maizy.ambient7.webapp.{ Ambient7WebAppStack, AppConfig }
Expand All @@ -30,7 +30,7 @@ class Co2ReportServlet(val appConfig: AppConfig)
val (from, to, device) = getReportParams
val aggregates = DB readOnly { implicit session =>
Co2Service.getHourlyAggregates(
device.agentId,
device.agent,
from,
to
)
Expand All @@ -42,7 +42,7 @@ class Co2ReportServlet(val appConfig: AppConfig)
val (from, to, device) = getReportParams
val aggregates = DB readOnly { implicit session =>
Co2Service.computeDailyAggregates(
device.agentId,
device.agent,
from,
to
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package ru.maizy.ambient7.webapp.servlet.helper
*/

import org.scalatra.ScalatraBase
import ru.maizy.ambient7.webapp.data.Co2Device
import ru.maizy.ambient7.core.data.Co2Device


trait DeviceParamSupport extends ScalatraBase {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,26 @@ package ru.maizy.ambient7.core.config
*/

import java.nio.file.Path
import ru.maizy.ambient7.core.data.{ AgentTags, Co2Device, Devices }

case class FromCliDevice(
agent: String = "main",
tags: AgentTags = AgentTags.empty
)

case class Ambient7Options(
universalConfigPath: Option[Path] = None,
influxDb: Option[InfluxDbOptions] = None,
mainDb: Option[DbOptions] = None,
devices: Option[Devices] = None,
selectedDeviceId: Option[String] = None,
fromCliDevice: Option[FromCliDevice] = None,

// TODO: fix this little hack
showHelp: Boolean = false
)
{

def selectedCo2Device: Option[Co2Device] =
this.selectedDeviceId.flatMap { id => devices.flatMap(_.co2Devices.find(_.id == id)) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package ru.maizy.ambient7.core.config.reader

import ru.maizy.ambient7.core.config.{ Ambient7Options, Defaults, FromCliDevice, ParsingError }
import ru.maizy.ambient7.core.data.AgentTags

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2017
* See LICENSE.txt for details.
*/


trait DevicesConfigReader extends UniversalConfigReader {

private def cliDeviceOpts(opts: Ambient7Options)(save: FromCliDevice => FromCliDevice): Ambient7Options =
opts.copy(fromCliDevice = Some(save(opts.fromCliDevice.getOrElse(FromCliDevice()))))

def fillDeviceFromCliOptions(): Unit = {

cliParser.opt[String]("agent-name")
.valueName { Defaults.INFLUXDB_AGENT_NAME }
.action { (value, opts) => cliDeviceOpts(opts)(_.copy(agent = value)) }

val saveTags = (value: String, opts: Ambient7Options) => cliDeviceOpts(opts)(_.copy(tags = AgentTags(value)))
val validateTags = (value: String) => AgentTags.tryParseFromString(value) match {
case Left(error) => cliParser.failure(error)
case Right(_) => cliParser.success
}

cliParser.opt[String]("agent-tags")
.valueName { "position=outdoor,altitude=200,some=val\\,ue" }
.validate(validateTags)
.action(saveTags)
.text { "Any additional InfluxDB record tags"}

// Deprecated
cliParser.opt[String]("influxdb-tags")
.action(saveTags)
.validate(validateTags)
.text { "Deprecated, use --agent-tags"}

()
}

def fillDevicesOptions(): Unit = {
// FIXME: implements

()
}

def fillSelectedDeviceOptions(): Unit = {
cliParser.opt[String]("device-id")
.action { (value, opts) => opts.copy(selectedDeviceId = Some(value)) }
.text { "Selected device" }

// FIXME: implement device append (here or in case class)
()
}

def co2DeviceRequired(): Unit = {
appendCheck { opts =>
val fromCliDefined = opts.fromCliDevice.isDefined
val agentByIdDefined = opts.selectedDeviceId.isDefined
if (fromCliDefined && agentByIdDefined) {
Left(ParsingError.withMessage("Either --agent-name or --device-id should be defined, but not both"))
} else if (opts.selectedDeviceId.isDefined && opts.selectedCo2Device.isEmpty){
val id = opts.selectedDeviceId.getOrElse("wtf?")
Left(ParsingError.withMessage(s"co2 device with id '$id' not found in config"))
} else {
Right(())
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ package ru.maizy.ambient7.core.data
* See LICENSE.txt for details.
*/

case class Co2AgentId(agentName: String, tags: AgentTags)
case class Co2Agent(agentName: String, tags: AgentTags) {
val id: String = s"${agentName}__${tags.encoded}"
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ case class Co2AggregatedLevels(
unknownLevel: Int,
from: ZonedDateTime,
to: ZonedDateTime,
agentId: Co2AgentId
agentId: Co2Agent
) {
override def toString: String = s"Co2AggregatedLevels(low=$lowLevel, med=$mediumLevel, high=$highLevel, " +
s"unknown=$unknownLevel, $from->$to, agent=${agentId.agentName}, tags=${agentId.tags})"
Expand Down
12 changes: 12 additions & 0 deletions core/src/main/scala/ru/maizy/ambient7/core/data/Co2Device.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package ru.maizy.ambient7.core.data

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2016-2017
* See LICENSE.txt for details.
*/

case class Co2Device(id: String, agent: Co2Agent) extends Device {
val deviceType = DeviceType.CO2

override def uid: String = s"co2__${id}__${agent.id}"
}
10 changes: 10 additions & 0 deletions core/src/main/scala/ru/maizy/ambient7/core/data/Device.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ru.maizy.ambient7.core.data

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2017
* See LICENSE.txt for details.
*/
trait Device {
def deviceType: DeviceType.Type
def uid: String
}
11 changes: 11 additions & 0 deletions core/src/main/scala/ru/maizy/ambient7/core/data/DeviceType.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ru.maizy.ambient7.core.data

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2017
* See LICENSE.txt for details.
*/

object DeviceType extends Enumeration {
type Type = Value
val CO2 = Value
}
10 changes: 10 additions & 0 deletions core/src/main/scala/ru/maizy/ambient7/core/data/Devices.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package ru.maizy.ambient7.core.data

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2017
* See LICENSE.txt for details.
*/

case class Devices(co2Devices: List[Co2Device]) {
def allDevices: List[Device] = co2Devices
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ru.maizy.ambient7.core.json

import ru.maizy.ambient7.core.data.Co2Agent

/**
* Copyright (c) Nikita Kovaliov, maizy.ru, 2016-2017
* See LICENSE.txt for details.
*/

trait Co2AgentProtocol extends BaseProtocol with AgentTagsProtocol {

implicit val agentProtocol = jsonFormat(Co2Agent, "name", "tags")
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ package ru.maizy.ambient7.core.json
import spray.json.{ JsNumber, JsObject, JsValue, RootJsonFormat, pimpAny }
import ru.maizy.ambient7.core.data.Co2AggregatedLevels

trait Co2AggregatedLevelsProtocol extends Co2AgentIdProtocol with DateTimeProtocol {
trait Co2AggregatedLevelsProtocol extends Co2AgentProtocol with DateTimeProtocol {

implicit object Co2AggregatedLevelsFormat extends RootJsonFormat[Co2AggregatedLevels] {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import scala.annotation.tailrec
import scala.util.{ Failure, Success, Try }
import com.typesafe.scalalogging.LazyLogging
import scalikejdbc._
import ru.maizy.ambient7.core.data.{ Co2AgentId, Co2AggregatedLevels }
import ru.maizy.ambient7.core.data.{ Co2Agent, Co2AggregatedLevels }
import ru.maizy.ambient7.core.util.DateTimeIterator
import ru.maizy.ambient7.core.util.Dates.dateTimeForUser

Expand All @@ -21,7 +21,7 @@ object Co2Service extends LazyLogging {
val DB_ZONE = ZoneOffset.UTC
val DB_DATE_FORMAT = DateTimeFormatter.ISO_LOCAL_DATE

def detectStartDateTime(agentId: Co2AgentId)(implicit db: DBSession): Either[String, Option[ZonedDateTime]] = {
def detectStartDateTime(agentId: Co2Agent)(implicit db: DBSession): Either[String, Option[ZonedDateTime]] = {
// TODO: readonly transaction

val query = sql"""
Expand Down Expand Up @@ -53,7 +53,7 @@ object Co2Service extends LazyLogging {

def addOrUpdateAggregate(
aggregate: Co2AggregatedLevels,
agentId: Co2AgentId)(implicit db: DBSession): Either[String, Unit] = {
agentId: Co2Agent)(implicit db: DBSession): Either[String, Unit] = {

val day = dateTimeToDbDate(aggregate.from)
val hour = dateTimeToDbHour(aggregate.from)
Expand All @@ -78,7 +78,7 @@ object Co2Service extends LazyLogging {
}

def getHourlyAggregates(
agentId: Co2AgentId,
agentId: Co2Agent,
from: ZonedDateTime,
to: ZonedDateTime)(implicit db: DBSession): Seq[Co2AggregatedLevels] = {

Expand Down Expand Up @@ -129,7 +129,7 @@ object Co2Service extends LazyLogging {
}

def computeDailyAggregates(
agentId: Co2AgentId,
agentId: Co2Agent,
from: ZonedDateTime,
to: ZonedDateTime)(implicit db: DBSession): Seq[Co2AggregatedLevels] = {

Expand Down

0 comments on commit 654fb7d

Please sign in to comment.