Я пытаюсь вычислить среднее значение температуры для 3 разных комнат, где в каждой комнате есть 3 датчика температуры.Я использую Flink (на Java).Сначала я делю датчики ключом, который является комнатой (A, B или C), и создаю им RichFlatMapFunction
, который содержит MapState
для сохранения температуры, пока у меня нет до 3 измерений.После трех измерений я вычисляю среднее значение.Чтобы использовать MapState
, мне нужен MapStateDescriptor
, который я не знаю, как правильно создать экземпляр.Может кто-то помочь мне с этим?Спасибо.
public class SensorsMultipleReadingMqttEdgentQEP2 {
private boolean checkpointEnable = false;
private long checkpointInterval = 10000;
private CheckpointingMode checkpointMode = CheckpointingMode.EXACTLY_ONCE;
public SensorsMultipleReadingMqttEdgentQEP2() throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setStreamTimeCharacteristic(TimeCharacteristic.IngestionTime);
if (checkpointEnable) {
env.enableCheckpointing(checkpointInterval, checkpointMode);
}
DataStream<MqttTemperature> temperatureStream01 = env.addSource(new TemperatureMqttConsumer("topic-edgent-01"));
DataStream<MqttTemperature> temperatureStream02 = env.addSource(new TemperatureMqttConsumer("topic-edgent-02"));
DataStream<MqttTemperature> temperatureStream03 = env.addSource(new TemperatureMqttConsumer("topic-edgent-03"));
DataStream<Tuple2<String, Double>> averageStream01 = temperatureStream01.map(new SensorMatcher()).keyBy(0)
.flatMap(new AverageTempMapper());
DataStream<Tuple2<String, Double>> averageStream02 = temperatureStream02.map(new SensorMatcher()).keyBy(0)
.flatMap(new AverageTempMapper());
DataStream<Tuple2<String, Double>> averageStream03 = temperatureStream03.map(new SensorMatcher()).keyBy(0)
.flatMap(new AverageTempMapper());
DataStream<Tuple2<String, Double>> averageStreams = averageStream01.union(averageStream02)
.union(averageStream03);
averageStreams.print();
env.execute("SensorsMultipleReadingMqttEdgentQEP");
}
public static class SensorMatcher implements MapFunction<MqttTemperature, Tuple2<String, MqttTemperature>> {
private static final long serialVersionUID = 7035756567190539683L;
@Override
public Tuple2<String, MqttTemperature> map(MqttTemperature value) throws Exception {
String key = "no-room";
if (value.getId().equals(1) || value.getId().equals(2) || value.getId().equals(3)) {
key = "room-A";
} else if (value.getId().equals(4) || value.getId().equals(5) || value.getId().equals(6)) {
key = "room-B";
} else if (value.getId().equals(7) || value.getId().equals(8) || value.getId().equals(9)) {
key = "room-C";
} else {
System.err.println("Sensor not defined in any room.");
}
return new Tuple2<>(key, value);
}
}
public static class AverageTempMapper
extends RichFlatMapFunction<Tuple2<String, MqttTemperature>, Tuple2<String, Double>> {
private static final long serialVersionUID = -4780146677198295204L;
private MapState<String, Tuple2<Integer, Double>> modelState;
@Override
public void open(Configuration parameters) throws Exception {
TypeInformation<Tuple2<String, Tuple2<Integer, Double>>> typeInformation = TypeInformation
.of(new TypeHint<Tuple2<String, Tuple2<Integer, Double>>>() {
});
// HOW TO INSTANTIATE THIS descriptor?
MapStateDescriptor<String, Tuple2<Integer, Double>> descriptor = new MapStateDescriptor<>("modelState",
String.class, Tuple2.class);
modelState = getRuntimeContext().getMapState(descriptor);
}
@Override
public void flatMap(Tuple2<String, MqttTemperature> value, Collector<Tuple2<String, Double>> out)
throws Exception {
Double temp = null;
Integer count = 0;
if (modelState.contains(value.f0)) {
count = modelState.get(value.f0).f0 + 1;
temp = (modelState.get(value.f0).f1 + value.f1.getTemp());
} else {
count = 1;
temp = value.f1.getTemp();
}
modelState.put(value.f0, Tuple2.of(count, temp));
if (count >= 3) {
out.collect(Tuple2.of("room", null));
}
}
}
}