From 03c72fcf1988539d1517c1009abef2f70fa5de99 Mon Sep 17 00:00:00 2001 From: Yatharth Ranjan Date: Mon, 18 Dec 2017 16:01:04 +0000 Subject: [PATCH 01/11] Update version --- java-sdk/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-sdk/build.gradle b/java-sdk/build.gradle index b0eeb3ee..34930d32 100644 --- a/java-sdk/build.gradle +++ b/java-sdk/build.gradle @@ -17,7 +17,7 @@ subprojects { apply plugin: 'idea' // Configuration - version = '0.2.3' + version = '0.2.4-SNAPSHOT' group = 'org.radarcns' ext.githubRepoName = 'RADAR-CNS/RADAR-Schemas' From 8c51b0aee725eced4f2647d6401ca526cfe9bc9c Mon Sep 17 00:00:00 2001 From: Joris Borgdorff Date: Thu, 4 Jan 2018 11:07:12 +0100 Subject: [PATCH 02/11] Fixed jetty dependency definitions --- java-sdk/radar-schemas-tools/build.gradle | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/java-sdk/radar-schemas-tools/build.gradle b/java-sdk/radar-schemas-tools/build.gradle index 24adc95c..4d27984f 100644 --- a/java-sdk/radar-schemas-tools/build.gradle +++ b/java-sdk/radar-schemas-tools/build.gradle @@ -34,11 +34,12 @@ dependencies { exclude group: 'org.slf4j', module: 'slf4j-log4j12' } implementation group: 'org.eclipse.jetty', name: 'jetty-server', version: jettyVersion - implementation group: 'org.eclipse.jetty', name: 'jetty-servlet', version: jettyVersion implementation group: 'org.glassfish.jersey.core', name: 'jersey-server', version: jerseyVersion - implementation group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet-core', version: jerseyVersion - implementation group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: jerseyVersion + // source catalogue service annotations + api group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet-core', version: jerseyVersion + + runtimeOnly group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: jerseyVersion runtimeOnly group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.25' testCompile group: 'junit', name: 'junit', version: junitVersion From 03ee35288911fd9753613ba3a444e852304963cb Mon Sep 17 00:00:00 2001 From: Joris Borgdorff Date: Thu, 4 Jan 2018 11:55:24 +0100 Subject: [PATCH 03/11] Documented KafkaTopics and made wait for brokers public --- .../schema/registration/KafkaTopics.java | 77 ++++++++++++++----- 1 file changed, 57 insertions(+), 20 deletions(-) diff --git a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/registration/KafkaTopics.java b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/registration/KafkaTopics.java index 8d2651d7..feba0c08 100644 --- a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/registration/KafkaTopics.java +++ b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/registration/KafkaTopics.java @@ -24,12 +24,19 @@ import static org.radarcns.schema.CommandLineApp.matchTopic; +/** + * Registers Kafka topics with Zookeeper. + */ public class KafkaTopics implements Closeable { private static final Logger logger = LoggerFactory.getLogger(KafkaTopics.class); private static final int MAX_SLEEP = 32; private final ZkUtils zkUtils; + /** + * Create Kafka topics registration object with given Zookeeper. + * @param zookeeper comma-separated list of Zookeeper 'hostname:port'. + */ public KafkaTopics(String zookeeper) { ZkClient zkClient = new ZkClient(zookeeper, 15_000, 10_000); @@ -48,11 +55,57 @@ public Object deserialize(byte[] bytes) throws ZkMarshallingError { zkUtils = new ZkUtils(zkClient, new ZkConnection(zookeeper), false); } + /** + * Wait for brokers to become available. This uses a polling mechanism, + * waiting for at most 200 seconds. + * @param brokers number of brokers to wait for + * @return whether the brokers where available + * @throws InterruptedException + * @throws KeeperException + */ + public boolean waitForBrokers(int brokers) throws InterruptedException, KeeperException { + boolean brokersAvailable = false; + int sleep = 2; + for (int tries = 0; tries < 10; tries++) { + int activeBrokers = getNumberOfBrokers(); + brokersAvailable = activeBrokers >= brokers; + if (brokersAvailable) { + logger.info("Kafka brokers available. Starting topic creation."); + break; + } + + if (tries < 9) { + logger.warn("Only {} out of {} Kafka brokers available. Waiting {} seconds.", + activeBrokers, brokers, sleep); + Thread.sleep(sleep * 1000L); + sleep = Math.min(MAX_SLEEP, sleep * 2); + } else { + logger.error("Only {} out of {} Kafka brokers available. Failed to wait on all brokers.", + activeBrokers, brokers, sleep); + } + } + return brokersAvailable; + } + + /** + * Create all topics in a catalogue. + * @param catalogue source catalogue to extract topic names from + * @param partitions number of partitions per topic + * @param replication number of replicas for a topic + * @return whether the whole catalogue was registered + */ public boolean createTopics(SourceCatalogue catalogue, int partitions, int replication) { return catalogue.getTopicNames() .allMatch(topic -> createTopic(topic, partitions, replication)); } + /** + * Create a single topic. + * @param topic name of the topic to create + * @param partitions number of partitions per topic + * @param replication number of replicas for a topic + * @return whether the topic was registered + */ public boolean createTopic(String topic, int partitions, int replication) { Properties props = new Properties(); try { @@ -79,6 +132,9 @@ public void close() { zkUtils.close(); } + /** + * Create a KafkaTopics command to register topics from the command line. + */ public static SubCommand command() { return new KafkaTopicsCommand(); } @@ -103,7 +159,7 @@ public int execute(Namespace options, CommandLineApp app) { int partitions = options.getInt("partitions"); String zookeeper = options.getString("zookeeper"); try (KafkaTopics topics = new KafkaTopics(zookeeper)) { - if (!waitForBrokers(topics, brokers)) { + if (!topics.waitForBrokers(brokers)) { logger.error("Kafka brokers not yet available. Aborting."); return 1; } @@ -135,25 +191,6 @@ public int execute(Namespace options, CommandLineApp app) { } } - private boolean waitForBrokers(KafkaTopics topics, int brokers) - throws InterruptedException, KeeperException { - boolean brokersAvailable = false; - int sleep = 2; - for (int tries = 0; tries < 10; tries++) { - int activeBrokers = topics.getNumberOfBrokers(); - brokersAvailable = activeBrokers >= brokers; - if (brokersAvailable) { - logger.info("Kafka brokers available. Starting topic creation."); - break; - } - logger.warn("Only {} out of {} Kafka brokers available. Waiting {} seconds.", - activeBrokers, brokers, sleep); - Thread.sleep(sleep * 1000L); - sleep = Math.min(MAX_SLEEP, sleep * 2); - } - return brokersAvailable; - } - @Override public void addParser(ArgumentParser parser) { parser.description("Create all topics that are missing on the Kafka server."); From 4cd766616a2cce31c33ea6e2ca34e1d90bda8715 Mon Sep 17 00:00:00 2001 From: Joris Borgdorff Date: Thu, 4 Jan 2018 12:12:04 +0100 Subject: [PATCH 04/11] Fixed gradle check --- java-sdk/radar-schemas-tools/build.gradle | 1 + .../java/org/radarcns/schema/registration/KafkaTopics.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/java-sdk/radar-schemas-tools/build.gradle b/java-sdk/radar-schemas-tools/build.gradle index 4d27984f..ae9d8b66 100644 --- a/java-sdk/radar-schemas-tools/build.gradle +++ b/java-sdk/radar-schemas-tools/build.gradle @@ -34,6 +34,7 @@ dependencies { exclude group: 'org.slf4j', module: 'slf4j-log4j12' } implementation group: 'org.eclipse.jetty', name: 'jetty-server', version: jettyVersion + implementation group: 'org.eclipse.jetty', name: 'jetty-servlet', version: jettyVersion implementation group: 'org.glassfish.jersey.core', name: 'jersey-server', version: jerseyVersion // source catalogue service annotations diff --git a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/registration/KafkaTopics.java b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/registration/KafkaTopics.java index feba0c08..b0ba5f80 100644 --- a/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/registration/KafkaTopics.java +++ b/java-sdk/radar-schemas-tools/src/main/java/org/radarcns/schema/registration/KafkaTopics.java @@ -80,7 +80,8 @@ public boolean waitForBrokers(int brokers) throws InterruptedException, KeeperEx Thread.sleep(sleep * 1000L); sleep = Math.min(MAX_SLEEP, sleep * 2); } else { - logger.error("Only {} out of {} Kafka brokers available. Failed to wait on all brokers.", + logger.error("Only {} out of {} Kafka brokers available." + + " Failed to wait on all brokers.", activeBrokers, brokers, sleep); } } From d989183df7a7aff3975154fec5049045115517f3 Mon Sep 17 00:00:00 2001 From: Joris Borgdorff Date: Tue, 9 Jan 2018 09:37:47 +0100 Subject: [PATCH 05/11] Added aggregate list and name to double aggregate This way, aggregates can be identified and there is a general aggregate list. --- commons/stream/aggregator/aggregate_list.avsc | 10 ++++++++ ...aggregation.avsc => double_aggregate.avsc} | 9 +++---- .../aggregator/double_array_aggregation.avsc | 15 ------------ ...gation.avsc => phone_usage_aggregate.avsc} | 3 ++- specifications/stream/android_phone.yml | 6 ++--- specifications/stream/biovotion_vsm1.yml | 24 +++++++++---------- specifications/stream/empatica_e4.yml | 16 ++++++------- 7 files changed, 40 insertions(+), 43 deletions(-) create mode 100644 commons/stream/aggregator/aggregate_list.avsc rename commons/stream/aggregator/{double_aggregation.avsc => double_aggregate.avsc} (67%) delete mode 100644 commons/stream/aggregator/double_array_aggregation.avsc rename commons/stream/aggregator/{phone_usage_aggregation.avsc => phone_usage_aggregate.avsc} (93%) diff --git a/commons/stream/aggregator/aggregate_list.avsc b/commons/stream/aggregator/aggregate_list.avsc new file mode 100644 index 00000000..45004024 --- /dev/null +++ b/commons/stream/aggregator/aggregate_list.avsc @@ -0,0 +1,10 @@ +{ + "namespace": "org.radarcns.stream.aggregator", + "type": "record", + "name": "AggregateList", + "doc": "Result of data aggregation.", + "version": "1.0.0", + "fields": [ + { "name": "fields", "type": {"type": "array", "items": "DoubleAggregate" }, "doc": "Aggregation of each of the underlying elements." } + ] +} diff --git a/commons/stream/aggregator/double_aggregation.avsc b/commons/stream/aggregator/double_aggregate.avsc similarity index 67% rename from commons/stream/aggregator/double_aggregation.avsc rename to commons/stream/aggregator/double_aggregate.avsc index 1552211a..3298290e 100644 --- a/commons/stream/aggregator/double_aggregation.avsc +++ b/commons/stream/aggregator/double_aggregate.avsc @@ -1,15 +1,16 @@ { "namespace": "org.radarcns.stream.aggregator", "type": "record", - "name": "DoubleAggregation", + "name": "DoubleAggregate", "doc": "Result of data aggregation.", + "version": "1.0.0", "fields": [ + { "name": "name", "type": "string", "doc": "Name of the field that has been aggregated over." }, { "name": "min", "type": "double", "doc": "State the minimum between accumulated values." }, { "name": "max", "type": "double", "doc": "State the maximum between accumulated values." }, { "name": "sum", "type": "double", "doc": "State the sum of accumulated values." }, { "name": "count", "type": "double", "doc": "Count the accumulated values." }, - { "name": "avg", "type": ["null", "double"], "doc": "State the avg between accumulated values.", "default": null }, - { "name": "quartile", "type": ["null", {"type": "array", "items": "double"}], "doc": "Quartile of accumulated values.", "default": null }, - { "name": "iqr", "type": ["null", "double"], "doc": "State the interquartile range between accumulated values.", "default": null } + { "name": "average", "type": ["null", "double"], "doc": "State the avg between accumulated values.", "default": null }, + { "name": "quartile", "type": ["null", {"type": "array", "items": "double"}], "doc": "Quartile of accumulated values.", "default": null } ] } diff --git a/commons/stream/aggregator/double_array_aggregation.avsc b/commons/stream/aggregator/double_array_aggregation.avsc deleted file mode 100644 index b52b7231..00000000 --- a/commons/stream/aggregator/double_array_aggregation.avsc +++ /dev/null @@ -1,15 +0,0 @@ -{ - "namespace": "org.radarcns.stream.aggregator", - "type": "record", - "name": "DoubleArrayAggregation", - "doc": "Result of data aggregation.", - "fields": [ - { "name": "min", "type": {"type": "array", "items": "double"}, "doc": "For each component, it states the minimum between accumulated values." }, - { "name": "max", "type": {"type": "array", "items": "double"}, "doc": "For each component, it States the maximum between accumulated values." }, - { "name": "sum", "type": {"type": "array", "items": "double"}, "doc": "For each component, it States the sum of accumulated values." }, - { "name": "count", "type": {"type": "array", "items": "double"}, "doc": "For each component, it counts the accumulated values." }, - { "name": "avg", "type": {"type": "array", "items": "double"}, "doc": "For each component, it states the avg between accumulated values." }, - { "name": "quartile", "type": {"type": "array", "items": {"type": "array", "items": "double"}}, "doc": "Quartile of accumulated values per component." }, - { "name": "iqr", "type": {"type": "array", "items": "double"}, "doc": "For each component, it states the interquartile range between accumulated values." } - ] -} diff --git a/commons/stream/aggregator/phone_usage_aggregation.avsc b/commons/stream/aggregator/phone_usage_aggregate.avsc similarity index 93% rename from commons/stream/aggregator/phone_usage_aggregation.avsc rename to commons/stream/aggregator/phone_usage_aggregate.avsc index deea8c14..7ceff7a9 100644 --- a/commons/stream/aggregator/phone_usage_aggregation.avsc +++ b/commons/stream/aggregator/phone_usage_aggregate.avsc @@ -1,8 +1,9 @@ { "namespace": "org.radarcns.stream.aggregator", "type": "record", - "name": "PhoneUsageAggregation", + "name": "PhoneUsageAggregate", "doc": "Aggregate time and opening events for an app.", + "version": "1.0.0", "fields": [ {"name": "packageName", "type": "string", "doc": "Package name of the app in use."}, {"name": "durationInForeground", "type":"double", "doc":"Total time in milliseconds the app was in the foreground."}, diff --git a/specifications/stream/android_phone.yml b/specifications/stream/android_phone.yml index e5c71980..eaafe482 100644 --- a/specifications/stream/android_phone.yml +++ b/specifications/stream/android_phone.yml @@ -3,13 +3,13 @@ doc: Aggregation of Phone data master: .stream.phone.PhoneStreamMaster data: - input_topic: android_phone_acceleration - value_schema: .stream.aggregator.DoubleArrayAggregation + value_schema: .stream.aggregator.AggregateList windowed: true - input_topic: android_phone_usage_event value_schema: .passive.phone.PhoneUsageEvent - input_topic: android_phone_usage_event_output - value_schema: .stream.aggregator.PhoneUsageAggregation + value_schema: .stream.aggregator.PhoneUsageAggregate windowed: true - input_topic: android_phone_battery_level - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true diff --git a/specifications/stream/biovotion_vsm1.yml b/specifications/stream/biovotion_vsm1.yml index e5ba4376..0f28ef6f 100644 --- a/specifications/stream/biovotion_vsm1.yml +++ b/specifications/stream/biovotion_vsm1.yml @@ -3,38 +3,38 @@ doc: Aggregation of Biovotion data master: .kafka.stream.biovotion.BiovotionVsm1Master data: - input_topic: android_biovotion_vsm1_acceleration - value_schema: .stream.aggregator.DoubleArrayAggregation + value_schema: .stream.aggregator.AggregateList windowed: true - input_topic: android_biovotion_vsm1_battery_level - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true - input_topic: android_biovotion_vsm1_blood_volume_pulse - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true - input_topic: android_biovotion_vsm1_energy - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true - input_topic: android_biovotion_vsm1_galvanic_skin_response - value_schema: .stream.aggregator.DoubleArrayAggregation + value_schema: .stream.aggregator.AggregateList windowed: true - input_topic: android_biovotion_vsm1_heartrate - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true - input_topic: android_biovotion_vsm1_heartrate_variability - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true - input_topic: android_biovotion_vsm1_led_current - value_schema: .stream.aggregator.DoubleArrayAggregation + value_schema: .stream.aggregator.AggregateList windowed: true - input_topic: android_biovotion_vsm1_ppg_raw - value_schema: .stream.aggregator.DoubleArrayAggregation + value_schema: .stream.aggregator.AggregateList windowed: true - input_topic: android_biovotion_vsm1_respiration_rate - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true - input_topic: android_biovotion_vsm1_oxygen_saturation - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true - input_topic: android_biovotion_vsm1_temperature - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true diff --git a/specifications/stream/empatica_e4.yml b/specifications/stream/empatica_e4.yml index a28e26ad..9f215a59 100644 --- a/specifications/stream/empatica_e4.yml +++ b/specifications/stream/empatica_e4.yml @@ -3,29 +3,29 @@ doc: Aggregation and conversion of Empatica E4 data master: .kafka.stream.biovotion.EmpaticaE4Master data: - input_topic: android_empatica_e4_acceleration - value_schema: .stream.aggregator.DoubleArrayAggregation + value_schema: .stream.aggregator.AggregateList windowed: true - input_topic: android_empatica_e4_battery_level - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true - input_topic: android_empatica_e4_blood_volume_pulse - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true - input_topic: android_empatica_e4_electrodermal_activity - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true - input_topic: android_empatica_e4_inter_beat_interval - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true - input_topic: android_empatica_e4_temperature - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true - type: HEART_RATE unit: BEATS_PER_MIN input_topic: android_empatica_e4_inter_beat_interval topic_base: android_empatica_e4_heart_rate windowed: true - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate - input_topic: android_empatica_e4_heartrate - value_schema: .stream.aggregator.DoubleAggregation + value_schema: .stream.aggregator.DoubleAggregate windowed: true From efcf641c69a7b235ba982a3e4073ca51d7af05e0 Mon Sep 17 00:00:00 2001 From: Joris Borgdorff Date: Tue, 9 Jan 2018 10:47:36 +0100 Subject: [PATCH 06/11] Updated aggregate documentation and scope --- commons/stream/aggregator/aggregate_list.avsc | 4 ++-- ...ble_aggregate.avsc => numeric_aggregate.avsc} | 8 ++++---- specifications/stream/android_phone.yml | 2 +- specifications/stream/biovotion_vsm1.yml | 16 ++++++++-------- specifications/stream/empatica_e4.yml | 14 +++++++------- 5 files changed, 22 insertions(+), 22 deletions(-) rename commons/stream/aggregator/{double_aggregate.avsc => numeric_aggregate.avsc} (68%) diff --git a/commons/stream/aggregator/aggregate_list.avsc b/commons/stream/aggregator/aggregate_list.avsc index 45004024..63338c1f 100644 --- a/commons/stream/aggregator/aggregate_list.avsc +++ b/commons/stream/aggregator/aggregate_list.avsc @@ -2,9 +2,9 @@ "namespace": "org.radarcns.stream.aggregator", "type": "record", "name": "AggregateList", - "doc": "Result of data aggregation.", + "doc": "A list of aggregated data, each item aggregating over a single field.", "version": "1.0.0", "fields": [ - { "name": "fields", "type": {"type": "array", "items": "DoubleAggregate" }, "doc": "Aggregation of each of the underlying elements." } + { "name": "fields", "type": {"type": "array", "items": "NumericAggregate" }, "doc": "Aggregates of each of the underlying elements." } ] } diff --git a/commons/stream/aggregator/double_aggregate.avsc b/commons/stream/aggregator/numeric_aggregate.avsc similarity index 68% rename from commons/stream/aggregator/double_aggregate.avsc rename to commons/stream/aggregator/numeric_aggregate.avsc index 3298290e..ab220c9a 100644 --- a/commons/stream/aggregator/double_aggregate.avsc +++ b/commons/stream/aggregator/numeric_aggregate.avsc @@ -1,16 +1,16 @@ { "namespace": "org.radarcns.stream.aggregator", "type": "record", - "name": "DoubleAggregate", - "doc": "Result of data aggregation.", + "name": "NumericAggregate", + "doc": "Basic statistics on a numeric value type.", "version": "1.0.0", "fields": [ { "name": "name", "type": "string", "doc": "Name of the field that has been aggregated over." }, { "name": "min", "type": "double", "doc": "State the minimum between accumulated values." }, { "name": "max", "type": "double", "doc": "State the maximum between accumulated values." }, { "name": "sum", "type": "double", "doc": "State the sum of accumulated values." }, - { "name": "count", "type": "double", "doc": "Count the accumulated values." }, - { "name": "average", "type": ["null", "double"], "doc": "State the avg between accumulated values.", "default": null }, + { "name": "count", "type": "int", "doc": "Count the accumulated values." }, + { "name": "mean", "type": ["null", "double"], "doc": "State the arithmetic mean between accumulated values.", "default": null }, { "name": "quartile", "type": ["null", {"type": "array", "items": "double"}], "doc": "Quartile of accumulated values.", "default": null } ] } diff --git a/specifications/stream/android_phone.yml b/specifications/stream/android_phone.yml index eaafe482..910ff5a2 100644 --- a/specifications/stream/android_phone.yml +++ b/specifications/stream/android_phone.yml @@ -11,5 +11,5 @@ data: value_schema: .stream.aggregator.PhoneUsageAggregate windowed: true - input_topic: android_phone_battery_level - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true diff --git a/specifications/stream/biovotion_vsm1.yml b/specifications/stream/biovotion_vsm1.yml index 0f28ef6f..a61518b1 100644 --- a/specifications/stream/biovotion_vsm1.yml +++ b/specifications/stream/biovotion_vsm1.yml @@ -6,22 +6,22 @@ data: value_schema: .stream.aggregator.AggregateList windowed: true - input_topic: android_biovotion_vsm1_battery_level - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true - input_topic: android_biovotion_vsm1_blood_volume_pulse - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true - input_topic: android_biovotion_vsm1_energy - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true - input_topic: android_biovotion_vsm1_galvanic_skin_response value_schema: .stream.aggregator.AggregateList windowed: true - input_topic: android_biovotion_vsm1_heartrate - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true - input_topic: android_biovotion_vsm1_heartrate_variability - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true - input_topic: android_biovotion_vsm1_led_current value_schema: .stream.aggregator.AggregateList @@ -30,11 +30,11 @@ data: value_schema: .stream.aggregator.AggregateList windowed: true - input_topic: android_biovotion_vsm1_respiration_rate - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true - input_topic: android_biovotion_vsm1_oxygen_saturation - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true - input_topic: android_biovotion_vsm1_temperature - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true diff --git a/specifications/stream/empatica_e4.yml b/specifications/stream/empatica_e4.yml index 9f215a59..48af57d4 100644 --- a/specifications/stream/empatica_e4.yml +++ b/specifications/stream/empatica_e4.yml @@ -6,26 +6,26 @@ data: value_schema: .stream.aggregator.AggregateList windowed: true - input_topic: android_empatica_e4_battery_level - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true - input_topic: android_empatica_e4_blood_volume_pulse - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true - input_topic: android_empatica_e4_electrodermal_activity - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true - input_topic: android_empatica_e4_inter_beat_interval - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true - input_topic: android_empatica_e4_temperature - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true - type: HEART_RATE unit: BEATS_PER_MIN input_topic: android_empatica_e4_inter_beat_interval topic_base: android_empatica_e4_heart_rate windowed: true - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate - input_topic: android_empatica_e4_heartrate - value_schema: .stream.aggregator.DoubleAggregate + value_schema: .stream.aggregator.NumericAggregate windowed: true From dca0d11dc325968c5516ae26e9fd913e79b1bcbc Mon Sep 17 00:00:00 2001 From: Joris Borgdorff Date: Mon, 15 Jan 2018 11:02:55 +0100 Subject: [PATCH 07/11] Use same time definition in AggregateKey as other objects --- commons/kafka/aggregate_key.avsc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/commons/kafka/aggregate_key.avsc b/commons/kafka/aggregate_key.avsc index e60a04d2..ee73ddb0 100644 --- a/commons/kafka/aggregate_key.avsc +++ b/commons/kafka/aggregate_key.avsc @@ -7,7 +7,7 @@ {"name": "projectId", "type": ["null", "string"], "doc": "Project that the key belongs to.", "default": null}, {"name": "userId", "type": "string", "doc": "User Identifier created during the enrolment."}, {"name": "sourceId", "type": "string", "doc": "Unique identifier associated with the source."}, - {"name": "start", "type": "long", "doc": "First timestamp in UNIX time contained in the time window."}, - {"name": "end", "type": "long", "doc": "Last timestamp in UNIX time contained in the time window."} + {"name": "timeStart", "type": "double", "doc": "Time (seconds since the UNIX Epoch) of the time window start."}, + {"name": "timeEnd", "type": "double", "doc": "Time (seconds since the UNIX Epoch) of the time window end."} ] } From 435f2c9f512c049e34d50a6af8cb662eee8fce8c Mon Sep 17 00:00:00 2001 From: Joris Borgdorff Date: Mon, 15 Jan 2018 11:04:31 +0100 Subject: [PATCH 08/11] Add tools to artifactory --- java-sdk/radar-schemas-tools/build.gradle | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/java-sdk/radar-schemas-tools/build.gradle b/java-sdk/radar-schemas-tools/build.gradle index 24adc95c..38835bcc 100644 --- a/java-sdk/radar-schemas-tools/build.gradle +++ b/java-sdk/radar-schemas-tools/build.gradle @@ -5,6 +5,8 @@ plugins { id 'application' } +apply plugin: 'com.jfrog.artifactory' + ext.artifactName = 'radar-schemas-tools' ext.description = 'RADAR Schemas specification and validation tools.' @@ -140,3 +142,19 @@ bintray { } } } + +artifactory { + contextUrl = 'https://oss.jfrog.org/artifactory' + publish { + repository { + repoKey = 'oss-snapshot-local' + username = project.hasProperty('bintrayUser') ? project.property('bintrayUser') : System.getenv('BINTRAY_USER') + password = project.hasProperty('bintrayApiKey') ? project.property('bintrayApiKey') : System.getenv('BINTRAY_API_KEY') + maven = true + } + } +} + +artifactoryPublish { + publications('RadarCommonsPublication') +} From a28e7f841074c7bd6901fefdd238e9a90118a9d3 Mon Sep 17 00:00:00 2001 From: Joris Borgdorff Date: Mon, 15 Jan 2018 11:58:43 +0100 Subject: [PATCH 09/11] Version bump: radar-schemas version 0.3 --- java-sdk/README.md | 6 +++--- java-sdk/build.gradle | 2 +- java-sdk/schema.json | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 java-sdk/schema.json diff --git a/java-sdk/README.md b/java-sdk/README.md index 35a3c856..f921b930 100644 --- a/java-sdk/README.md +++ b/java-sdk/README.md @@ -9,13 +9,13 @@ repositories { dependencies { // Commons schemas (backend, passive remote monitoring app) - compile 'org.radarcns:radar-schemas-commons:0.2.2' + compile 'org.radarcns:radar-schemas-commons:0.3' // REST API schemas (REST API, testing) - compile 'org.radarcns:radar-schemas-restapi:0.2.2' + compile 'org.radarcns:radar-schemas-restapi:0.3' // Questionnaire schemas (active remote monitoring app) - compile 'org.radarcns:radar-schemas-questionnaire:0.2.2' + compile 'org.radarcns:radar-schemas-tools:0.3' } ``` Usually, you only need to include the schemas you actually need in your dependencies. diff --git a/java-sdk/build.gradle b/java-sdk/build.gradle index 34930d32..e76f8d01 100644 --- a/java-sdk/build.gradle +++ b/java-sdk/build.gradle @@ -17,7 +17,7 @@ subprojects { apply plugin: 'idea' // Configuration - version = '0.2.4-SNAPSHOT' + version = '0.3' group = 'org.radarcns' ext.githubRepoName = 'RADAR-CNS/RADAR-Schemas' diff --git a/java-sdk/schema.json b/java-sdk/schema.json new file mode 100644 index 00000000..74f2f2c7 --- /dev/null +++ b/java-sdk/schema.json @@ -0,0 +1 @@ +{"schema":"{\"type\":\"record\",\"name\":\"ThincItTrails\",\"namespace\":\"org.radarcns.active.thincit\",\"doc\":\"THINC-it Assessment derived from Trail Making B. 17 trials. Each trial is the transition from one circle to another.\",\"fields\":[{\"name\":\"time\",\"type\":\"double\",\"doc\":\"Timestamp in UTC (s) when the test is submitted to the subject.\"},{\"name\":\"timeCompleted\",\"type\":\"double\",\"doc\":\"Timestamp in UTC (s) when the subject completes the test.\"},{\"name\":\"score\",\"type\":\"int\",\"doc\":\"THINC-it index score - 0 to 4000.\"},{\"name\":\"duration\",\"type\":\"int\",\"doc\":\"Total time taken to complete the assessment in milliseconds.\"},{\"name\":\"layoutVersion\",\"type\":\"int\",\"doc\":\"Each play randomly select one of 40 pre-designed layouts.\"},{\"name\":\"wrongNode\",\"type\":\"int\",\"doc\":\"The number of times that the subject transitioned to an incorrect next circle before successful transition to correct next circle.\"},{\"name\":\"lostContact\",\"type\":\"int\",\"doc\":\"The number of times that the mouse button has been released before transitioning successfully to next circle.\"},{\"name\":\"longestTrial\",\"type\":\"int\",\"doc\":\"Longest trial completion time expressed in milliseconds.\"},{\"name\":\"iqrCompletion\",\"type\":\"int\",\"doc\":\"Mean of trial completion times within interquartile range.\"},{\"name\":\"intervalOne\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalTwo\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalThree\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalFour\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalFive\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalSix\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalSeven\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalEight\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalNine\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalTen\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalEleven\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalTwelve\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalThirteen\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalFourteen\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalFifteen\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalSixteen\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalSeventeen\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"appVersion\",\"type\":\"int\",\"doc\":\"App version.\"}]}"} From 49f5b1ce35011f5a655c14cf534584240c6283ec Mon Sep 17 00:00:00 2001 From: Joris Borgdorff Date: Mon, 15 Jan 2018 13:47:25 +0100 Subject: [PATCH 10/11] Removed accidentaly added schema --- java-sdk/schema.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 java-sdk/schema.json diff --git a/java-sdk/schema.json b/java-sdk/schema.json deleted file mode 100644 index 74f2f2c7..00000000 --- a/java-sdk/schema.json +++ /dev/null @@ -1 +0,0 @@ -{"schema":"{\"type\":\"record\",\"name\":\"ThincItTrails\",\"namespace\":\"org.radarcns.active.thincit\",\"doc\":\"THINC-it Assessment derived from Trail Making B. 17 trials. Each trial is the transition from one circle to another.\",\"fields\":[{\"name\":\"time\",\"type\":\"double\",\"doc\":\"Timestamp in UTC (s) when the test is submitted to the subject.\"},{\"name\":\"timeCompleted\",\"type\":\"double\",\"doc\":\"Timestamp in UTC (s) when the subject completes the test.\"},{\"name\":\"score\",\"type\":\"int\",\"doc\":\"THINC-it index score - 0 to 4000.\"},{\"name\":\"duration\",\"type\":\"int\",\"doc\":\"Total time taken to complete the assessment in milliseconds.\"},{\"name\":\"layoutVersion\",\"type\":\"int\",\"doc\":\"Each play randomly select one of 40 pre-designed layouts.\"},{\"name\":\"wrongNode\",\"type\":\"int\",\"doc\":\"The number of times that the subject transitioned to an incorrect next circle before successful transition to correct next circle.\"},{\"name\":\"lostContact\",\"type\":\"int\",\"doc\":\"The number of times that the mouse button has been released before transitioning successfully to next circle.\"},{\"name\":\"longestTrial\",\"type\":\"int\",\"doc\":\"Longest trial completion time expressed in milliseconds.\"},{\"name\":\"iqrCompletion\",\"type\":\"int\",\"doc\":\"Mean of trial completion times within interquartile range.\"},{\"name\":\"intervalOne\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalTwo\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalThree\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalFour\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalFive\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalSix\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalSeven\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalEight\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalNine\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalTen\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalEleven\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalTwelve\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalThirteen\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalFourteen\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalFifteen\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalSixteen\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"intervalSeventeen\",\"type\":\"int\",\"doc\":\"Trial completion time in milliseconds.\"},{\"name\":\"appVersion\",\"type\":\"int\",\"doc\":\"App version.\"}]}"} From 3297513cb31c6fff5af5400b679b1d3be685d8de Mon Sep 17 00:00:00 2001 From: Joris Borgdorff Date: Mon, 15 Jan 2018 13:55:22 +0100 Subject: [PATCH 11/11] Updated gradle wrapper and travis build cache --- .travis.yml | 13 ++++++++++--- java-sdk/build.gradle | 17 +++++++++++++++-- java-sdk/gradle/wrapper/gradle-wrapper.jar | Bin 54708 -> 54329 bytes .../gradle/wrapper/gradle-wrapper.properties | 2 +- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 72e0f4e1..eb6f57c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,15 @@ jdk: env: - TERM=dumb +cache: + directories: + - $HOME/.gradle/caches/jars-1 + - $HOME/.gradle/caches/jars-2 + - $HOME/.gradle/caches/jars-3 + - $HOME/.gradle/caches/modules-2/files-2.1/ + - $HOME/.gradle/native + - $HOME/.gradle/wrapper + deploy: - provider: releases api_key: ${GH_TOKEN} @@ -27,6 +36,4 @@ deploy: before_install: - cd java-sdk - -before_deploy: - - pwd + - ./gradlew downloadDependencies diff --git a/java-sdk/build.gradle b/java-sdk/build.gradle index e76f8d01..e29c3848 100644 --- a/java-sdk/build.gradle +++ b/java-sdk/build.gradle @@ -130,7 +130,20 @@ subprojects { } } +task downloadDependencies { + description "Pre-downloads *most* dependencies" + doLast { + configurations.getAsMap().each { name, config -> + println "Retrieving dependencies for $name" + try { + config.files + } catch (e) { + project.logger.info e.message // some cannot be resolved, silentlyish skip them + } + } + } +} + task wrapper(type: Wrapper) { - gradleVersion = '4.1' - distributionType 'all' + gradleVersion '4.4' } diff --git a/java-sdk/gradle/wrapper/gradle-wrapper.jar b/java-sdk/gradle/wrapper/gradle-wrapper.jar index 7a3265ee94c0ab25cf079ac8ccdf87f41d455d42..01b8bf6b1f99cad9213fc495b33ad5bbab8efd20 100644 GIT binary patch delta 15814 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 diff --git a/java-sdk/gradle/wrapper/gradle-wrapper.properties b/java-sdk/gradle/wrapper/gradle-wrapper.properties index bf1b63c3..933b6473 100644 --- a/java-sdk/gradle/wrapper/gradle-wrapper.properties +++ b/java-sdk/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip