How can I add extra data to Alte Beacon - altbeacon

I was building a beacon with AlteBeacon library, this was created fined but I would like to add extra data but I do not know how to do that. For example I would like to register product name and price in my new beacon.
public class Tab1Register extends Fragment {
private BluetoothAdapter blVer;
private TextView device;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.tab1reg, container, false);
device = rootView.findViewById(R.id.device);
blVer = BluetoothAdapter.getDefaultAdapter();
boolean le2MPhySupported;
//device.setText("hola");
if (Build.VERSION.SDK_INT >= 21) {
// Call some material design APIs here
device.setText("supported");
Beacon beacon = new Beacon.Builder()
.setId1("2f234454-cf6d-4a0f-adf2-f4911ba9ffa6")
.setId2("1")
.setId3("2")
.setManufacturer(0x0118)
.setTxPower(-59)
.setDataFields(Arrays.asList(new Long[] {0l}))
.setBluetoothName("Paulo")
.build();
BeaconParser beaconParser = new BeaconParser()
.setBeaconLayout("m:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25");
BeaconTransmitter beaconTransmitter = new BeaconTransmitter(getActivity(), beaconParser);
beaconTransmitter.startAdvertising(beacon);
} else {
// Implement this feature without material design
device.setText("Not supported");
}
return rootView;
}

Understand that there is limited data space in a BLE advertisement. Each beacon format has a different number of data bytes available. For iBeacon, the number is 0 bytes, for Eddystone-UID, the number is 2 bytes and for AltBeacon, there is one byte.
The code shown in the question already adds this one byte of data to the advertisement, giving it a value of 0. If you want to change the value to 255, for example, change the code to this:
.setDataFields(Arrays.asList(new Long[] {255l}))
Don't let the fact that the data type in the setDataFields method takes an array of Long confuse you. Because only one byte is available in the single data field for this beacon format, you cannot store an entire long value (which would be 8 bytes) in the data field. The value must be between 0-255.

Related

Better way to detect WiFi enabled/disabled on iOS?

After an unbelievable amount of teeth gnashing, I finally have a method that successfully detects if WiFi is enabled on iOS independent of whether it's connected or not. There are at least a couple uses for such a thing, and I don't think this violates the spirit or the letter of Apple Law(tm).
However, it's ugly and probably won't work forever. It currently works on iOS 10.2.1, as of Jan 31, 2017. I'll put my answer below and hope that someone can improve it. I've heavily researched Reachability (doesn't meet the requirements), CaptiveNetwork, HotspotHelper, SCNetworkConfiguration, Xamarin's System.Net.NetworkInterface, and more. This is it that actually works as far as I can tell.
The gist of the solution is that when there's TWO interfaces reported by getifaddrs() with the name "awdl0" then WiFi is enabled. Just one and it's disabled.
I credit pebble8888 for pointing me to https://github.com/alirp88/SMTWiFiStatus which is Objective-C, where the lack of comments make it hard to understand what's going on or what the author's intention was.
Here's my full and complete Xamarin/C# solution, which ought to be pretty readable for any other major language user:
using System;
using System.Runtime.InteropServices;
namespace Beacon.iOS
{
/// <summary>
/// code stolen from the Xamarin source code to work around goofy interactions between
/// the good-god-why-would-it-work-that-way iOS and the entirely reasonable Xamarin
/// (it doesn't report interfaces that are reported multiple times)
/// </summary>
class XamHack
{
//
// Types
//
internal struct ifaddrs
{
#pragma warning disable 0649
public IntPtr ifa_next;
public string ifa_name;
public uint ifa_flags;
public IntPtr ifa_addr;
public IntPtr ifa_netmask;
public IntPtr ifa_dstaddr;
public IntPtr ifa_data;
#pragma warning restore
}
//
// OS methods
//
[DllImport("libc")]
protected static extern int getifaddrs(out IntPtr ifap);
[DllImport("libc")]
protected static extern void freeifaddrs(IntPtr ifap);
//
// Methods
//
/// <summary>
/// Our glorious hack. I apologize to the programming gods for my sins
/// but this works (for now) and functionality trumps elegance. Even this.
/// Reverse engineered from: https://github.com/alirp88/SMTWiFiStatus
/// </summary>
public static bool IsWifiEnabled()
{
int count = 0;
IntPtr ifap;
// get the OS to put info about all the NICs into a linked list of buffers
if (getifaddrs(out ifap) != 0)
throw new SystemException("getifaddrs() failed");
try
{
// iterate throug those buffers
IntPtr next = ifap;
while (next != IntPtr.Zero)
{
// marshall the data into our struct
ifaddrs addr = (ifaddrs)Marshal.PtrToStructure(next, typeof(ifaddrs));
// count the instances of the sacred interface name
if ("awdl0" == addr.ifa_name)
count++;
// move on to the next interface
next = addr.ifa_next;
}
}
finally
{
// leaking memory is for jerks
freeifaddrs(ifap);
}
// if there's two of the sacred interface, that means WiFi is enabled. Seriously.
return (2 == count);
}
} // class
} // namespace

In Unity3d, How can I read the position data from .txt file continuously?

In Unity3D, I want to load position data from text file. Here is an example of the text file. These are simulation results. The simulation program generate 30 data per a second. So, I want to visualize result in realtime. The contents are x, y, z position.
data_01.txt
1 -5 -10
data_ 02.txt
2 2 5
data_03.txt
3 2 4
...............
All files consist of 1 line.
I'd like to input these data into a object.
I want to load text file in 30 text files per 1 second.
I write code that read first text file.
But, I need some advice about reading text file continuously. I want to read 1 text file per frame.
using UnityEngine;
using System.Collections;
using System;
using System.IO;
public class parsing : MonoBehaviour {
public string fileName = "Data_01.txt"
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (!File.Exists(fileName))
{
Debug.Log(fileName + "does not exist.");
return;
}
using (StreamReader sr = File.OpenText(fileName))
{
String fileData;
fileData = sr.ReadToEnd();
sr.Close();
Debug.Log("Data Read: " + fileData);
}
}
}
Transfering continuous data via text files is a pretty bad idea/approach.
You are better off using (for example) a tcp connection and send your simulation data to unity using .Nets' System.Net.Sockets (more precisely TcpListener and TcpClient).
See: https://msdn.microsoft.com/en-us/library/system.net.sockets(v=vs.110).aspx
(If you want to stick to your approach, you would have to know the name of the text files to read each Update(). You could use a counter variable (name it counter for example), that is incremented each Update(). That way you can glue together the current text file name like string filename = "data_" + counter.ToString("D2") + ".txt". (The ToString("D2") will add leading zeros if the value of counter is only one digit, e.g. 1 -> "01")

Custom List with lazy loading

I have successfully implemented like this for lazy loading in custom list
and the code I used for this is here:Custom List With Images in Blackberry
In the linked question, I position the y coordinate of heart icon and I resolved the problemm of linked Question.
if (logoThumbnailImage != null
&& logoThumbnailImage.length > index
&& logoThumbnailImage[index] != null) {
EncodedImage img = logoThumbnailImage[index];
graphics.drawImage(0, y + 10, Display.getWidth(),
Display.getHeight() - 100, img, 0, 0, 0);
graphics.drawImage(300,
y+400,
heart.getWidth(), heart.getHeight(), heart,
0, 0, 0);
Now I want to handle click event for both; that is, for list row click and on heart click
For that I saw a post written by #Nate here Custom List Field click event. But in that code the images are not loading from server and they are static Images. I want to implement #Nate's code with my code (That is lazy loading ).
If you have any Idea please suggest how can I do that. Thanks in Advance
Assuming you start with the code I posted in this answer, and use the code you show in this question to download images from a list of URLs, then you should be able to achieve lazy image loading with the following changes:
Create a listener interface that gets notified when downloads complete:
public interface DownloadListener {
// invokes if download success
public void downloadSuccess(Bitmap bitmap);
// invokes if download failed
public void errorOccured();
}
Then, the Manager subclass that represents one list row, CustomListRow, is modified to implement this interface, and update the _thumb image when the download completes:
public class CustomListRow extends Manager implements DownloadListener, FieldChangeListener {
public void downloadSuccess(final Bitmap img) {
_data.setThumb(img);
// make sure bitmap is updated on the UI / main thread
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
_thumb.setBitmap(img);
}
});
}
public void errorOccured() {
// TODO: handle error
}
Then, you'll need to add some code to create all your threads to download images in the background, and notify the DownloadListeners when the image downloads complete. You can decide where to do this. In my example, I will do this in my ListScreen class, where I instantiate the ListRander data objects and the CustomListField:
for (int i = 0; i < numberOfItem; i++) {
ListRander lr = new ListRander("Product Name " + i, icon); // icon is placeholder for thumbnail image
data.addElement(lr);
}
final CustomListField list = new CustomListField(data);
add(list);
list.setChangeListener(this);
pool = new ThreadPool(3); // 3 concurrent download threads
for (int i = 0; i < numberOfItem; i++) {
final int row = i;
// create a new runnable to download the next image, and resize it:
pool.assign(new Runnable() {
public void run() {
try {
String text=object[row].getJSONArray("UrlArray").getString(0).toString();
EncodedImage encodedImg = JPEGEncodedImage.encode(connectServerForImage(text), quality); //connectserverForImage load Images from server
EncodedImage logoThumbnail = sizeImage(encodedImg, Display.getWidth(), Display.getHeight()-100);
list.getRow(row).downloadSuccess(logoThumbnail.getBitmap());
} catch (Exception e) {
e.printStackTrace();
list.getRow(row).errorOccured();
}
}
}
});
}
You could do this in the ListScreen constructor, or whenever you have your object[] array of URLs.
You'll need to add a new method to CustomListField:
public CustomListRow getRow(int row) {
return (CustomListRow)getField(row);
}
The code above also needs a member variable added (in ListScreen) to create a thread pool:
private ThreadPool pool;
This thread pool implementation is based on this tutorial here, with very minor modifications, simply to change ArrayList (not available on BlackBerry Java) to Vector ... and removing the calls to Thread#destroy(). You'll need to copy that tutorial's ThreadPool, WorkerThread, and Done classes to your project. The above example I show creates a thread pool of 3 threads. On a single CPU smartphone, 2 or 3 threads is probably fine for your needs. Read more here if you want to get the perfect number of threads for your application.
Note: if possible, you can usually improve performance if you download images that are exactly the right size for your application, instead of burdening the network with larger images, and then resizing them inside your app. However, I realize that this depends on having some control over the images' web server, which you may not have. Just a thought for later optimization.
I am sure that I seen a good answer to this question on my travels, but can't find it now. I do recommend reviewing the BB forums here:
http://supportforums.blackberry.com/t5/Java-Development/bd-p/java_dev
as there are similar questions there.
For now, just the highlights of what you need to do:
Create an image downloading runnable to process the download - you have pretty much already done this in your previous code.
Use the Observer pattern (search the internet for this), so that the BitmapField is the Observer for the completion of your image downloading. So when the image has been downloaded, the Runnable invokes the observer, which can then update the Bitmap.
Use a Thread pool with a limited number of Threads (I would say 3), so that you do not start a whole load of image downloads at the same time. Search the internet for information on Thread Pool for help implementing this. You had not done this step in your previous example, and you can get away with running all the downloads, but I expect at some stage that this will fail.
Put these together and you have your solution. Not trivial I know. Good luck.

Javafx-2 tableview bindings with none text cells

I would like to show a series of financial transactions in a TableView.
Each Transaction consists of a Date, a Description and an Amount.
I can make this work using bindings if I treat all the cells as Text using the example shown in a reply to another question. This allows in cell editing which is my goal.
But I can't get it to work on the date and amount columns, I think I need a separate cell factory for each cell type and a possibly a separate updateItem method but I'm stuck.
Any pointers to an example or suggestions would be helpful.
You may want to check out the DataFX project at:
http://www.javafxdata.org/
and specifically the cell factories like:
http://www.javafxdata.org/javadoc/org/javafxdata/control/cell/TextFieldCellFactory.html
DataFX contains custom cell factories for several data types, tables, lists and tree views. Assuming that for example your amount has a double type, you could write something similar like that in a subclass of TableColum
(replace ??? by the class name of the class that represents a row in your table):
setCellFactory(TextFieldCellFactory.<???, Number>forTableColumn(new Callback<String,Number>(){
#Override
public Number call(String newValueStr) {
double newValue = Double.parseDouble(newValueStr);
return newValue;
}));
setOnEditCommit(new EventHandler<CellEditEvent<???, Number>>() {
#Override
public void handle(CellEditEvent<???, Number> t) {
double newValue = t.getNewValue().doubleValue();
// do something with the double value the user entered here
}
});
}
}
I hope that at least gives you some direction. I have left out Exception handling for clarity.

Very basic AChartEngine XY

I've been trying for hours to get something as simple as displaying a line chart based on 2 dots that I supply manually and all I get is a crash. I've tried to understand how everything works based on the demo code but it's too complex. I'm not even concerned about writing nice code with onResume() etc, I just want something to display the first time I open the activity. Once I know how to do that I'll be able to adapt and learn what I need. Here's the code I came up with:
public class StatsActivity extends Activity {
private XYMultipleSeriesDataset StatsDataset = new XYMultipleSeriesDataset();
private XYMultipleSeriesRenderer StatsRenderer = new XYMultipleSeriesRenderer();
private XYSeries StatsCurrentSeries;
private GraphicalView StatsChartView;
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.stats);
LinearLayout layout = (LinearLayout) findViewById(R.id.Statschart);
StatsRenderer.setAxesColor(Color.YELLOW);
String seriesTitle = "Rank";
XYSeries series = new XYSeries(seriesTitle);
series.add(5, 7); //1st series I want to add
StatsDataset.addSeries(series);
series.add(9, 1); //the 2nd one
StatsDataset.addSeries(series);
StatsCurrentSeries = series;
System.out.println(series);
XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setColor(Color.RED);
StatsRenderer.addSeriesRenderer(renderer);
StatsChartView = ChartFactory.getLineChartView(this, StatsDataset,StatsRenderer);
layout.addView(StatsChartView);
}
}
I've been reading the docs to determine what each function does but in the end I still can't get anything to display.
Thanks!
The big thing that I struggled with is that you need a renderer for each XYSeries. You have two series here, but just one renderer - I just create/add renderers when I input data. Also, Android is mostly pass-by-reference, so you've passed the same data set in twice (i.e. your second update to the data will be mirrored "in" the MultipleSeriesDataset).

Resources