We are trying to use Altbeacon library to satisfy the next study case:
We want to put several IBeacons in a room or corridor with a distance of no more than 3 meters between each of them, and we want to get the current closest Ibeacon based on the user phone which scans for the beacons.
We first tried to build regions with only one beacon each, wondering that a region were a closed set, meaning that when you enter in a region, you couldn’t be in other region at the same time, and when you leave a region, you enter in the next closest one and so. But that’s not the approach that the library implements.
We want to know if there’s any way in Altbeacon library to apply our approach or if some kind of patch has to be made to satisfy the study case that I present to you.
The easiest way to accomplish this goal is to range for all beacons using a single region, and start ranging:
#Override
public void onBeaconServiceConnect() {
try {
// Set up a region that matches all of your beacons. You may want to replace the first
// null with a UUID that all your beacons share.
Region allBeaconsRegion = new Region("all beacons", null, null, null);
beaconManager.startRangingBeaconsInRegion(mAllBeaconsRegion);
beaconManager.setRangeNotifier(this);
} catch (RemoteException e) {
Log.e(TAG, "Cannot connect to beacon service");
}
}
Note, if you are using a custom Application class with the RegionBootstrap, you can put the above code above inside the didEnterRegion method instead of inside the onBeaconServiceConnect method.
Once you start ranging, you will get a callback once per second with a list of all visible beacons. You can add code to determine which one is closest:
#Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region arg1) {
Beacon closestBeacon = null;
for (Beacon beacon : beacons) {
if (closestBeacon == null) {
closestBeacon = beacon;
}
else {
if (closestBeacon.getDistance() > beacon.getDistance()) {
closestBeacon = beacon;
}
}
}
// Do Something with closestBeacon here
}
Keep in mind that the closest beacon may change back and forth due to radio noise, so you probably need to add extra logic to protect against the closest beacon flipping back and forth too often.
Related
I have three fragments in a view pager:
A -> B -> C
I would like to get the strings of my two edittexts in Fragment A on swipe to Fragment B to show them in Fragment B. The edittext data may be changed up until the swipe.
Someone has suggested listening for typing and sending data after each one, but the callbacks I know for that change state EVERY key click (which can be expensive). How do I this without using buttons, since their right next to each other, for a more delightful experience?
You can check the data of the EditText on swipe ; if it's not null, then you can send it to any other fragment using Bundle since you are dealing with fragments
With help from #I. Leonard I found a solution here.
It was deprecated so I used the newer version. I put the below code in my fragment class because I needed access to the data without complicating things. It works like a charm!
On the page listener callback, I suggest, calling an interface for inter-fragment communication to do your actions on your home activity or to call the appropriate fragment that can do the work, from the activity.
// set content to next page on scroll start
vPager = (ViewPager) getActivity().findViewById(R.id.viewpager);
vPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_SETTLING) {
// ViewPager is slowing down to settle on a page
if (vPager.getCurrentItem() == 1) {
// The page to be settled on is the second (Preview) page
if (!areFieldsNull(boxOne.getText().toString(), boxTwo.getText().toString()))
// call interface method in view pager activity using interface reference
communicator.preview(boxOne.getText().toString(), boxTwo.getText().toString());
}
}
}
});
I've only began with DDD and currently trying to grasp the ways to do different things with it. I'm trying to design it using asynchronous events (no event-sourcing yet) with CQRS. Currently I'm stuck with validation of commands. I've read this question: Validation in a Domain Driven Design , however, none of the answers seem to cover complex validation across different aggregate roots.
Let's say I have these aggregate roots:
Client - contains list of enabled services, each service can have a value-object list of discounts and their validity.
DiscountOrder - an order to enable more discounts on some of the services of given client, contains order items with discount configuration.
BillCycle - each period when bills are generated is described by own billcycle.
Here's the usecase:
Discount order can be submitted. Each new discount period in discount order should not overlap with any of BillCycles. No two discounts of same type can be active at the same time on one service.
Basically, using Hibernate in CRUD style, this would look something similar to (java code, but question is language-agnostic):
public class DiscountProcessor {
...
#Transactional
public void processOrder(long orderId) {
DiscOrder order = orderDao.get(orderId);
BillCycle[] cycles = billCycleDao.getAll();
for (OrderItem item : order.getItems()) {
//Validate billcycle overlapping
for (BillCycle cycle : cycles) {
if (periodsOverlap(cycle.getPeriod(), item.getPeriod())) {
throw new PeriodsOverlapWithBillCycle(...);
}
}
//Validate discount overlapping
for (Discount d : item.getForService().getDiscounts()) {
if (d.getType() == item.getType() && periodsOverlap(d.getPeriod(), item.getPeriod())) {
throw new PeriodsOverlapWithOtherItems(...);
}
}
//Maybe some other validations in future or stuff
...
}
createDiscountsForOrder(order);
}
}
Now here are my thoughts on implementation:
Basically, the order can be in three states: "DRAFT", "VALIDATED" and "INVALID". "DRAFT" state can contain any kind of invalid data, "VALIDATED" state should only contain valid data, "INVALID" should contain invalid data.
Therefore, there should be a method which tries to switch the state of the order, let's call it order.validate(...). The method will perform validations required for shift of state (DRAFT -> VALIDATED or DRAFT -> INVALID) and if successful - change the state and transmit a OrderValidated or OrderInvalidated events.
Now, what I'm struggling with, is the signature of said order.validate(...) method. To validate the order, it requires several other aggregates, namely BillCycle and Client. I can see these solutions:
Put those aggregates directly into the validate method, like
order.validateWith(client, cycles) or order.validate(new
OrderValidationData(client, cycles)). However, this seems a bit
hackish.
Extract the required information from client and cycle
into some kind of intermediate validation data object. Something like
order.validate(new OrderValidationData(client.getDiscountInfos(),
getListOfPeriods(cycles)).
Do validation in a separate service
method which can do whatever it wants with whatever aggregates it
wants (basically similar to CRUD example above). However, this seems
far from DDD, as method order.validate() will become a dummy state
setter, and calling this method will make it possible to bring an
order unintuitively into an corrupted state (status = "valid" but
contains invalid data because nobody bothered to call validation
service).
What is the proper way to do it, and could it be that my whole thought process is wrong?
Thanks in advance.
What about introducing a delegate object to manipulate Order, Client, BillCycle?
class OrderingService {
#Injected private ClientRepository clientRepository;
#Injected private BillingRepository billRepository;
Specification<Order> validSpec() {
return new ValidOrderSpec(clientRepository, billRepository);
}
}
class ValidOrderSpec implements Specification<Order> {
#Override public boolean isSatisfied(Order order) {
Client client = clientRepository.findBy(order.getClientId());
BillCycle[] billCycles = billRepository.findAll();
// validate here
}
}
class Order {
void validate(ValidOrderSpecification<Order> spec) {
if (spec.isSatisfiedBy(this) {
validated();
} else {
invalidated();
}
}
}
The pros and cons of your three solutions, from my perspective:
order.validateWith(client, cycles)
It is easy to test the validation with order.
#file: OrderUnitTest
#Test public void should_change_to_valid_when_xxxx() {
Client client = new ClientFixture()...build()
BillCycle[] cycles = new BillCycleFixture()...build()
Order order = new OrderFixture()...build();
subject.validateWith(client, cycles);
assertThat(order.getStatus(), is(VALID));
}
so far so good, but there seems to be some duplicate test code for DiscountOrderProcess.
#file: DiscountProcessor
#Test public void should_change_to_valid_when_xxxx() {
Client client = new ClientFixture()...build()
BillCycle[] cycles = new BillCycleFixture()...build()
Order order = new OrderFixture()...build()
DiscountProcessor subject = ...
given(clientRepository).findBy(client.getId()).thenReturn(client);
given(cycleRepository).findAll().thenReturn(cycles);
given(orderRepository).findBy(order.getId()).thenReturn(order);
subject.processOrder(order.getId());
assertThat(order.getStatus(), is(VALID));
}
#or in mock style
#Test public void should_change_to_valid_when_xxxx() {
Client client = mock(Client.class)
BillCycle[] cycles = array(mock(BillCycle.class))
Order order = mock(Order.class)
DiscountProcessor subject = ...
given(clientRepository).findBy(client.getId()).thenReturn(client);
given(cycleRepository).findAll().thenReturn(cycles);
given(orderRepository).findBy(order.getId()).thenReturn(order);
given(client).....
given(cycle1)....
subject.processOrder(order.getId());
verify(order).validated();
}
order.validate(new OrderValidationData(client.getDiscountInfos(),
getListOfPeriods(cycles))
Same as the above one, you still need to prepare data for both OrderUnitTest and discountOrderProcessUnitTest. But I think this one is better as order is not tightly coupled with Client and BillCycle.
order.validate()
Similar to my idea if you keep validation in the domain layer. Sometimes it is just not any entity's responsibility, consider domain service or specification object.
#file: OrderUnitTest
#Test public void should_change_to_valid_when_xxxx() {
Client client = new ClientFixture()...build()
BillCycle[] cycles = new BillCycleFixture()...build()
Order order = new OrderFixture()...build();
Specification<Order> spec = new ValidOrderSpec(clientRepository, cycleRepository);
given(clientRepository).findBy(client.getId()).thenReturn(client);
given(cycleRepository).findAll().thenReturn(cycles);
subject.validate(spec);
assertThat(order.getStatus(), is(VALID));
}
#file: DiscountProcessor
#Test public void should_change_to_valid_when_xxxx() {
Order order = new OrderFixture()...build()
Specification<Order> spec = mock(ValidOrderSpec.class);
DiscountProcessor subject = ...
given(orderingService).validSpec().thenReturn(spec);
given(spec).isSatisfiedBy(order).thenReturn(true);
given(orderRepository).findBy(order.getId()).thenReturn(order);
subject.processOrder(order.getId());
assertThat(order.getStatus(), is(VALID));
}
Do the 3 possible states reflect your domain or is that just extrapolation ? I'm asking because your sample code doesn't seem to change Order state but throw an exception when it's invalid.
If it's acceptable for the order to stay DRAFT for a short period of time after being submitted, you could have DiscountOrder emit a DiscountOrderSubmitted domain event. A handler catches the event and (delegates to a Domain service that) examines if the submit is legit or not. It would then issue a ChangeOrderState command to make the order either VALIDATED or INVALID.
You could even suppose that the change is legit by default and have processOrder() directly take it to VALIDATED, until proven otherwise by a subsequent INVALID counter-order given by the validation service.
This is not much different from your third solution or Hippoom's one though, except every step of the process is made explicit with its own domain event. I guess that with your current aggregate design you're doomed to have a third party orchestrator (as un-DDD and transaction script-esque as it may sound) that controls the process, since the DiscountOrder aggregate doesn't have native access to all information to tell if a given transformation is valid or not.
I am trying to detect iBeacons with a specific UUID and Major. The didRangeBeaconsInRegion is being called but the Beacon collection it returns has 0 entries.
The below is my code (abridged a bit)
private static final String BEACON_UUID = "F8AD3E82-0D91-4D9B-B5C7-7324744B2026";
private static final int BEACON_MAJOR = 36582;
#Override
public void onIBeaconServiceConnect() {
iBeaconManager.setRangeNotifier(new RangeNotifier() {
#Override
public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) {
if (iBeacons.size() > 0) {
IBeacon thisBeacon = iBeacons.iterator().next();
}
}
});
try {
iBeaconManager.startRangingBeaconsInRegion(new Region("myUniqueID", BEACON_UUID, BEACON_MAJOR ,null));
} catch (RemoteException e) {
e.printStackTrace();
}
}
I am assuming I am doing my binding correctly as the didRangeBeaconsInRegion(..) is being called successfully.
I have used RadiusNetwork's own application to detected the beacons and that works fine and I can see them all so it is not seem to be an issue with Bluetooth on my device
A couple of tips:
Double check that your BEACON_UUID and BEACON_MAJOR are correct for the beacon that is transmitting. For testing, try setting both of these to null temporarily until you get it working, then you can set them back to the values you have.
It is normal for the iBeacons.size() to be zero sometimes if a beacon did not happen to be detected in a given cycle. But it should not always be of size zero. I'm not sure how you are testing, but try adding a Log.d(TAG, "Number of beacons detected: "+iBeacons.size()); and let it run to see if you ever get a non-zero number.
I suggest to check the uuid , major and minor values of your beacons and make them match with the region u want.
didRangeBeaconsInRegion should return an array af beacons.
You can use the "beecon" app to update easily the values.
Hope this can help you.
Regards.
I'm setting out to create a weather model display tool (web application), and from what I've seen, I'm really liking the idea of using Google Web Tools, and especially the SmartGWT toolkit. My one biggest sticking point at this point is finding some way to create a sort of image "looper" (displaying all images in a particular "set" one after another, not unlike a slide show). For reference, I need functionality (at least on a basic level) similar to this: http://rapidrefresh.noaa.gov/hrrrconus/jsloop.cgi?dsKeys=hrrr:&runTime=2012053007&plotName=cref_sfc&fcstInc=60&numFcsts=16&model=hrrr&ptitle=HRRR%20Model%20Fields%20-%20Experimental&maxFcstLen=15&fcstStrLen=-1&resizePlot=1&domain=full&wjet=1 (though it certainly need not be exactly like that).
Does anyone know of (ideally) some sort of GWT module that can do image looping? Or if not, does it sound like something an intermediate programmer could figure out without too much trouble (I'm willing to accept a challenge), even if I've never explicitly used GWT before? I'm sure I could whip together something that pulls each image in as it goes through a loop, but prefetching them would be even more ideal.
Please comment if you need clarification on anything!
As far as I'm aware there's not a pre-fab solution to do this, although maybe SmartGWT has something I don't know about. In any case, it won't be too hard to roll your own. Here's some code to get you started:
public class ImageLooper extends Composite {
// List of images that we will loop through
private final String[] imageUrls;
// Index of the image currently being displayed
private int currentImage = 0;
// The image element that will be displayed to the user
private final Image image = new Image();
// The Timer provides a means to execute arbitrary
// code after a delay or at regular intervals
private final Timer imageUpdateTimer = new Timer() {
public void run() {
currentImage = (currentImage + 1) % images.length;
image.setUrl(imageUrls[currentImage]);
}
}
// Constructor. I'll leave it to you how you're going to
// build your list of image urls.
public ImageLooper(String[] imageUrls) {
this.imageUrls = imageUrls;
// Prefetching the list of images.
for (String url : imageUrls)
Image.prefetch(url);
// Start by displaying the first image.
image.setUrl(imageUrls[0]);
// Initialize this Composite on the image. That means
// you can attach this ImageLooper to the page like you
// would any other Widget and it will show up as the
// image.
initWidget(image);
}
// Call this method to start the animation
public void playAnimation() {
// Update the image every two seconds
imageUpdateTimer.scheduleRepeating(2000);
}
// Call this method to stop the animation
public void stopAnimation() {
imageUpdateTimer.cancel();
}
}
One annoying thing with this implementation is that you have no way of knowing when your list of images has finished loading; Image.prefetch doesn't have a callback to help you here.
I'm using the code from the official site, and I am consistently seeing the same behavior on multiple test devices - instead of getting the current location of the device, it gets the previous location (up to 30 miles away, where I was an hour ago).
private void setupMaps()
{
watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
watcher.MovementThreshold = 10.0f;
watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_statusChanged);
watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);
new Thread(startLocServInBackground).Start();
}
void startLocServInBackground()
{
watcher.TryStart(true, TimeSpan.FromSeconds(60));
}
void watcher_statusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
switch (e.Status)
{
case GeoPositionStatus.Disabled:
// The Location Service is disabled or unsupported.
// Check to see if the user has disabled the location service.
if (watcher.Permission == GeoPositionPermission.Denied)
{
// the user has disabled LocServ on their device.
showMessage("Location is required but it is disabled. Turn it on in Settings");
}
else
{
showMessage("Location is not functioning on this phone. Sorry, Crux cannot run");
}
break;
case GeoPositionStatus.Initializing:
// The location service is initializing.
LoadingInfo.Text = "finding location";
break;
case GeoPositionStatus.NoData:
// The Location Service is working, but it cannot get location data
// due to poor signal fidelity (most likely)
// this fired intermittently when data was coming back :/
//MessageBox.Show("Location data is not available.");
break;
case GeoPositionStatus.Ready:
// The location service is working and is receiving location data.
//statusTextBlock.Text = "Location data is available.";
LoadingInfo.Text = "Location found";
// THIS FIRES AFTER POSITION CHANGED HAS STOPPED FIRING
break;
}
}
private void initPostPanel()
{
PostPanel.Visibility = Visibility.Visible;
}
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
// update the textblock readouts.
latitude = e.Position.Location.Latitude.ToString("0.0000000000");
longitude = e.Position.Location.Longitude.ToString("0.0000000000");
// THIS FIRES TWICE, BEFORE STATUS IS FIRED AS READY. THEN THIS DOESN'T CALL AGAIN
}
What I would expect to have happen is to get a continuous series of calls to PositionChanged after StatusChanged is called with a Status of Ready. If the calls continued after Ready, I expect I would eventually get the correct coordinates - but it never calls after that point.
This does not occur with the emulator, only on the actual device (making this extremely difficult to test - since it actually involves driving between each test!)
I am running the source code from the tutorial as well, and it does roughly the same.
Can anyone tell me more about the expected behavior here and how I get what I need - which is simply a set of coordinates for the device at the current location when the app is being used.
I had the same problem myself - there are 2 parts to this.
Turns out the GeoCoordinateWatcher returns the last known good position - which is almost always out of date. What I do is something like this:
Check that the status is GeoPositionStatus.Ready and then ensure the datetime of the position is recent (within the last 5 mins). You can then go further and check that e.Position.Location.HorizontalAccuracy <= 350 (so under 350m) - but doing this with the datetime check as well can cause the phone to take a long time to get a position the lower you set the accuracy, so it may be best to get an initial position with the date check, and then continue to try get a better position with the Accuracy check. I also start the watcher as soon as the app starts to get faster results.
The other issue is MovementThreshold. If you do as I said above, it might still take a while before you get an accurate position, and you will likely experience the intermittent problem you mentioned where it does not fire the 2nd time (it does eventually, depending how long you wait - this can be minutes). The best thing I have found is to start the GeoCoordinateWatcher with the threshold set to 0. Once you have got an accurate position, stop the watcher, set the threshold to the actual one you want (eg 10), and then start it again. If you set this without stopping first, it will not use the new value.
<!-- language: c# -->
GeoPositionStatus = CurrentGeoDeviceStatus;
static void geoCoordWatcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
{
CurrentGeoDeviceStatus = e.Status;
}
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
if (gpsReady && e.Position.Timestamp.DateTime.AddMinutes(5) > DateTime.Now)
{
latitude = e.Position.Location.Latitude.ToString("0.0000000000");
longitude = e.Position.Location.Longitude.ToString("0.0000000000");
locReady = true;
}
}
It looks like the fix was to block it from using the first value and getting it from the second event instead:
bool gpsReady = false;
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
if (gpsReady)
{
latitude = e.Position.Location.Latitude.ToString("0.0000000000");
longitude = e.Position.Location.Longitude.ToString("0.0000000000");
locReady = true;
}
gpsReady = true;
}
I'm still baffled about why I don't get more events or why it fires an incorrect value first, but the above code seems to be working.
One note, for anyone else trying this, is that you might think getting the value in the StatusChanged event would work, like so:
case GeoPositionStatus.Ready:
latitude = watcher.Position.Location.Latitude.ToString("0.0000000000");
longitude = watcher.Position.Location.Longitude.ToString("0.0000000000");
break;
I don't know why, but the above code seemed to work perfectly when I was running attached to the debugger and then frequently hung (that is, the event never fired and my UI seemed to hang) in practical use. I never managed to reproduced the issue while attached to the debugger.
UPDATE: It looks like this isn't working all of the time. In some cases it doesn't fire the second time and so my code never completes running. If anyone can provide more information around this that gets me closer to simply having the actual current location of the device without fail, I will definitely mark your answer as the answer. Thanks!