001package org.intellimate.izou.sdk.frameworks.presence.provider.template; 002 003import org.intellimate.izou.events.EventLifeCycle; 004import org.intellimate.izou.events.EventListenerModel; 005import org.intellimate.izou.events.EventModel; 006import org.intellimate.izou.identification.IdentificationManager; 007import org.intellimate.izou.sdk.Context; 008import org.intellimate.izou.sdk.activator.Activator; 009import org.intellimate.izou.sdk.events.CommonEvents; 010import org.intellimate.izou.sdk.events.Event; 011import org.intellimate.izou.sdk.frameworks.presence.events.LeavingEvent; 012import org.intellimate.izou.sdk.frameworks.presence.events.PresenceEvent; 013import org.intellimate.izou.sdk.frameworks.presence.resources.PresenceResourceHelper; 014import org.intellimate.izou.sdk.util.ResourceUser; 015 016import java.time.LocalDateTime; 017import java.time.temporal.ChronoUnit; 018import java.util.ArrayList; 019import java.util.Arrays; 020import java.util.List; 021import java.util.Optional; 022import java.util.concurrent.ExecutionException; 023import java.util.concurrent.TimeUnit; 024import java.util.concurrent.TimeoutException; 025 026/** 027 * the base class for all presence-things that have no CONSTANT information (for example a motion-sensor). 028 * if it is the first encountering with the user since he was discovered (and at least an hour has passed), 029 * the event also contains CommonEvents.Response.Major_Response as a descriptor. 030 * @author LeanderK 031 * @version 1.0 032 */ 033public abstract class PresenceNonConstant extends Activator implements PresenceResourceHelper, EventListenerModel, ResourceUser { 034 private boolean present; 035 private boolean strictPresent = false; 036 private LocalDateTime lastSeen = LocalDateTime.now(); 037 private final boolean strict; 038 private final boolean fireUnknownIfNotPresent; 039 040 /** 041 * @deprecated addResponseDescriptors not used anymore 042 */ 043 @Deprecated 044 public PresenceNonConstant(Context context, String ID, boolean strict, boolean fireUnknownIfNotPresent, 045 boolean addResponseDescriptors) { 046 this(context, ID, strict, fireUnknownIfNotPresent); 047 } 048 @SuppressWarnings("unused") 049 public PresenceNonConstant(Context context, String ID, boolean strict, boolean fireUnknownIfNotPresent) { 050 super(context, ID); 051 this.strict = strict; 052 this.fireUnknownIfNotPresent = fireUnknownIfNotPresent; 053 getContext().getEvents().registerEventListener(Arrays.asList(LeavingEvent.ID, PresenceEvent.ID), this); 054 try { 055 present = getIsPresent(false, true) 056 .get(1, TimeUnit.SECONDS); 057 } catch (InterruptedException | ExecutionException | TimeoutException e) { 058 present = true; 059 } 060 } 061 062 /** 063 * call this method when you have encountered the user 064 */ 065 @SuppressWarnings("unused") 066 public void userEncountered() { 067 List<String> descriptors = new ArrayList<>(); 068 /* 069 if (strict && ((!present && !fireUnknownIfNotPresent)|| !strictPresent) && addResponseDescriptors) { 070 if (lastSeen.until(LocalDateTime.now(), ChronoUnit.MINUTES) > getMajorMinuteThresholdNotPresent()) { 071 descriptors.add(CommonEvents.Response.MAJOR_RESPONSE_DESCRIPTOR); 072 } else if (lastSeen.until(LocalDateTime.now(), ChronoUnit.MINUTES) > getMinorMinuteThresholdNotPresent()) { 073 descriptors.add(CommonEvents.Response.MINOR_RESPONSE_DESCRIPTOR); 074 } 075 } else if (present && strict && addResponseDescriptors) { 076 if (lastSeen.until(LocalDateTime.now(), ChronoUnit.MINUTES) > getMajorMinuteThresholdPresent()) { 077 descriptors.add(CommonEvents.Response.MAJOR_RESPONSE_DESCRIPTOR); 078 } else if (lastSeen.until(LocalDateTime.now(), ChronoUnit.MINUTES) > getMinorMinuteThresholdNotPresent()) { 079 descriptors.add(CommonEvents.Response.MINOR_RESPONSE_DESCRIPTOR); 080 } 081 }*/ 082 descriptors.add(CommonEvents.Descriptors.NOT_INTERRUPT); 083 boolean known = !fireUnknownIfNotPresent || present; 084 boolean firstPresent = (!strict && !present) || (strict && !strictPresent); 085 long lastSeen = this.lastSeen.until(LocalDateTime.now(), ChronoUnit.SECONDS); 086 Optional<Event> presenceEvent = IdentificationManager.getInstance() 087 .getIdentification(this) 088 .flatMap(id -> PresenceEvent.createPresenceEvent(id, strict, known, firstPresent, descriptors, lastSeen)) 089 .map(event -> event.addEventLifeCycleListener(EventLifeCycle.APPROVED, lifeCycle -> { 090 if (known) { 091 this.lastSeen = LocalDateTime.now(); 092 if (strict) 093 this.strictPresent = true; 094 present = true; 095 } 096 })); 097 if (!presenceEvent.isPresent()) { 098 error("unable to create PresenceEvent"); 099 } else { 100 fire(presenceEvent.get(), 5); 101 } 102 } 103 104 105 /** 106 * Invoked when an activator-event occurs. 107 * 108 * @param event an instance of Event 109 */ 110 @Override 111 public void eventFired(EventModel event) { 112 if (event.containsDescriptor(LeavingEvent.ID) || event.containsDescriptor(PresenceEvent.ID)) { 113 if (event.containsDescriptor(LeavingEvent.ID)) { 114 if (event.containsDescriptor(LeavingEvent.GENERAL_DESCRIPTOR)) { 115 present = false; 116 strictPresent = false; 117 } else if (event.containsDescriptor(LeavingEvent.STRICT_DESCRIPTOR)) { 118 nonStrictAvailable().thenAccept(available -> { 119 if (!available) 120 present = false; 121 strictPresent = false; 122 }); 123 } 124 } else { 125 present = true; 126 if (event.containsDescriptor(PresenceEvent.STRICT_DESCRIPTOR)) 127 strictPresent = true; 128 } 129 if (event.containsDescriptor(PresenceEvent.STRICT_DESCRIPTOR)) 130 lastSeen = LocalDateTime.now(); 131 } 132 } 133}