Repository navigation
Feature-type objects do not receive any data from SensorTile #6
Copy link
Copy link
Open
Description
Hello Giovanni,
I'm creating an app to monitor a dog's activities through motion, microphone level, and audio features.
I have created a unique activity and a single layout where I manage the above features plus the battery.
The battery code is commented because I do not need it right now.
This is the code of the only activity that follows the activity of the node search (ScanActivity):
`public class MainActivity extends AppCompatActivity {
/**
* create an intent for start the activity that will log the information from the node
*
* @param c context used for create the intent
* @param node note that will be used by the activity
* @return intent for start this activity
*/
public static Intent getStartIntent(Context c, @NonNull Node node) {
Intent i = new Intent(c, MainActivity.class);
i.putExtra(NODE_TAG, node.getTag());
i.putExtras(NodeContainerFragment.prepareArguments(node));
return i;
}
private final static String NODE_FRAGMENT = MainActivity.class.getCanonicalName() + "" +
".NODE_FRAGMENT";
private final static String NODE_TAG = MainActivity.class.getCanonicalName() + "" +
".NODE_TAG";
/** fragment used for keep the connection open */
private NodeContainerFragment mNodeContainer;
/**
* nodo che mostrerà i dati
*/
private Node mNode;
// Feature on which to apply the listener
private FeatureActivity mfeatureAct;
private FeatureMicLevel mMicLevel;
//private FeatureBattery mBattery;
private FeatureAudioADPCM mAudio;
// feature where we read the audio sync values
private FeatureAudioADPCMSync mAudioSync;
// Audio track builder
private AudioTrack mAudioTrack;
// The sampling rate
private static final int SAMPLE_RATE = 8000;
//object containing the sync data needed in a ADPCM stream decoding
private BVAudioSyncManager mBVAudioSyncManager = new BVAudioSyncManager();
// audio manager
private static final int AUDIO_STREAM = AudioManager.STREAM_MUSIC;
private boolean mIsRecording;
private AudioBuffer mRecordedAudio;
private static final int MAX_RECORDING_TIME_S = 30;
/**
* listner FeatureActivity and FeatureMicLevel
*/
FeatureActivity.ActivityType event;
public final Feature.FeatureListener mfeatureRecognListner = new Feature.FeatureListener(){
@Override
public void onUpdate(Feature f, Feature.Sample sample) {
if (f.getName().equals("Activity Recognition")) {
event = FeatureActivity.getActivityStatus(sample);
}
}//onUpdate
};//FeatureActivityRecognitionListner
byte levelMic;
public Feature.FeatureListener mMicLevelListner = new Feature.FeatureListener(){
@Override
public void onUpdate(Feature f, Feature.Sample sample) {
if (f.getName().equals("Mic Level")){
levelMic = FeatureMicLevel.getMicLevel(sample,1); ///DUBBIO
}
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if ((event.equals(FeatureActivity.ActivityType.STATIONARY) || event.equals(FeatureActivity.ActivityType.WALKING)) &&
levelMic < 60) {
mStatusImage.setImageResource(R.drawable.cane_zen);
mStatusText.setText("Calm");
mStatusText.setBackgroundColor(Color.GREEN);
}
// quando abbaia più di 6 volte in 10 sec, il cane è nervoso
int count = 0;
if (levelMic > 100) {
count++;
for (int i = 0; i == 10; i++) {
if (levelMic > 100) {
count++;
if (count > 6) {
mStatusImage.setImageResource(R.drawable.cane_nervoso);
mStatusText.setText("Nervous");
mStatusText.setBackgroundColor(Color.RED);
}
}
}
}
else if (levelMic >= 60 && levelMic <= 100) {
mStatusImage.setImageResource(R.drawable.cane_giocoso);
mStatusText.setText("Playful");
mStatusText.setBackgroundColor(Color.YELLOW);
}
}
});
}//onUpdate
};//FeatureMicLevelListner
// /**
// * listner FeatureBattery
// */
// float levelBat;
// public final Feature.FeatureListener mBatteryListner = new Feature.FeatureListener() {
// @Override
// public void onUpdate(Feature f, Feature.Sample sample){
// if (f.getName().equals("Battery")) {
// levelBat = FeatureBattery.getBatteryLevel(sample);
//
// MainActivity.this.runOnUiThread(new Runnable() {
// @Override
// public void run() {
//
// if(levelBat == 0.0){
// mBatteryImage.setImageResource(R.drawable.battery_00);
// mBatteryText.setText("Low battery");
// }
// if(levelBat == 20.0){
// mBatteryImage.setImageResource(R.drawable.battery_20);
// mBatteryText.setText("Battery about to die");
// }
// if(levelBat == 40.0){
// mBatteryImage.setImageResource(R.drawable.battery_40);
// mBatteryText.setText("40%");
// }
// if(levelBat == 60.0){
// mBatteryImage.setImageResource(R.drawable.battery_60);
// mBatteryText.setText("60%");
// }
// if(levelBat == 80.0){
// mBatteryImage.setImageResource(R.drawable.battery_80);
// mBatteryText.setText("80%");
// }
// if(levelBat == 100.0){
// mBatteryImage.setImageResource(R.drawable.battery_100);
// mBatteryText.setText("Battery charged");
// }
//
// }
// });
//
// }
// }
//
// };
/**
* listener for the audio feature, it will updates the audio values
*/
public final Feature.FeatureListener mAudioListener = new Feature.FeatureListener() {
@Override
public void onUpdate(final Feature f, final Feature.Sample sample) {
short[] audioSample = FeatureAudioADPCM.getAudio(sample);
/* Write audio data for playback
* @param short : The array that contains the data for playback
* @param int: offset in rawAudio where playback data begins
* @param int: The number of shorts to read in rawAudio after the offset
*/
mAudioTrack.write(audioSample,0,audioSample.length);
}
};
/**
* listener for the audioSync feature, it will update the synchronism values
*/
public final Feature.FeatureListener mAudioSyncListener = new Feature.FeatureListener() {
@Override
public void onUpdate(Feature f, final Feature.Sample sample) {
if(mBVAudioSyncManager!=null){
mBVAudioSyncManager.setSyncParams(sample);
}
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ImageView mStatusImage;
TextView mStatusText;
ImageView mBatteryImage;
TextView mBatteryText;
Button mPlayButton;
Button mStopButton;
SeekBar mVolumeBar;
FloatingActionButton mRecordButton;
ProgressBar mRecordBar;
AudioManager mAudioManager;
private TextView mRequestStatus;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// find the node.
String nodeTag = getIntent().getStringExtra(NODE_TAG);
mNode = Manager.getSharedInstance().getNodeWithTag(nodeTag);
//create/recover the NodeContainerFragment (DebugConsoleActivity.java)
if (savedInstanceState == null) {
Intent i = getIntent();
mNodeContainer = new NodeContainerFragment();
mNodeContainer.setArguments(i.getExtras());
getFragmentManager().beginTransaction()
.add(mNodeContainer, NODE_FRAGMENT).commit();
} else {
mNodeContainer = (NodeContainerFragment) getFragmentManager()
.findFragmentByTag(NODE_FRAGMENT);
}//if-else
mfeatureAct = mNode.getFeature(FeatureActivity.class);
mMicLevel = mNode.getFeature(FeatureMicLevel.class);
//mBattery = mNode.getFeature(FeatureBattery.class);
mAudio = mNode.getFeature(FeatureAudioADPCM.class);
mAudioSync = mNode.getFeature(FeatureAudioADPCMSync.class);
//builder audio track
mAudioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
FeatureAudioADPCM.AUDIO_PACKAGE_SIZE,
AudioTrack.MODE_STREAM);
mStatusImage = (ImageView)findViewById(R.id.statusImage);
mStatusText = (TextView)findViewById(R.id.statusText);
mBatteryImage = (ImageView)findViewById(R.id.batteryImage);
mBatteryText = (TextView)findViewById(R.id.batteryText);
mPlayButton = (Button) findViewById(R.id.playButton);
mStopButton = (Button) findViewById(R.id.stopButton);
mVolumeBar = (SeekBar)findViewById(R.id.volumeBar);
mRecordBar = (ProgressBar) findViewById(R.id.recordTimeValue);
mRecordBar.setIndeterminate(false);
mRecordButton = (FloatingActionButton) findViewById(R.id.recordButton);
mRequestStatus = (TextView) findViewById(R.id.requestStatus);
// When the play button is pressed
mPlayButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mAudioTrack.play();
mAudioManager.setStreamVolume(AUDIO_STREAM,mVolumeBar.getProgress(),0);
}
});
//When the stop button is pressed
mStopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopAudioTrack();
mAudioManager.setStreamVolume(AUDIO_STREAM,0,0);
}
});
//enable control volume
setVolumeControlStream(AudioManager.STREAM_MUSIC);
initControls();
}
private void stopAudioTrack(){
synchronized(this) {
mAudioTrack.pause();
mAudioTrack.flush();
}
}
// Volume control from SeekBar
private void initControls()
{
try
{
mVolumeBar = (SeekBar)findViewById(R.id.volumeBar);
mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
mVolumeBar.setMax(mAudioManager
.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
mVolumeBar.setProgress(mAudioManager
.getStreamVolume(AudioManager.STREAM_MUSIC));
mVolumeBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
{
@Override
public void onStopTrackingTouch(SeekBar arg0)
{
}
@Override
public void onStartTrackingTouch(SeekBar arg0)
{
}
@Override
public void onProgressChanged(SeekBar arg0, int progress, boolean arg2)
{
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
progress, 0);
}
});
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public void onResume() {
super.onResume();
// Feature Activity Listner
mfeatureAct.addFeatureListener(mfeatureRecognListner);
mNode.enableNotification(mfeatureAct);
mNode.readFeature(mfeatureAct);
// Feature MicLevel Listner
mMicLevel.addFeatureListener(mMicLevelListner);
mNode.enableNotification(mMicLevel);
mNode.readFeature(mMicLevel);
// Feature Battery Listner
// mBattery.addFeatureListener(mBatteryListner);
// mNode.enableNotification(mBattery);
// mNode.readFeature(mBattery);
// Features Audio Listner
if(mAudio!=null && mAudioSync!=null) {
mAudio.addFeatureListener(mAudioListener);
mBVAudioSyncManager.reinitResetFlag();
mAudio.setAudioSyncManager(mBVAudioSyncManager);
mNode.enableNotification(mAudio);
mAudioSync.addFeatureListener(mAudioSyncListener);
mNode.enableNotification(mAudioSync);
}
}
@Override
public void onPause() {
super.onPause();
// Feature Activity Listner
mfeatureAct.removeFeatureListener(mfeatureRecognListner);
mNode.disableNotification(mfeatureAct);
// Feature MicLevel Listner
mMicLevel.removeFeatureListener(mMicLevelListner);
mNode.disableNotification(mMicLevel);
// Feature Battery Listner
// mBattery.removeFeatureListener(mBatteryListner);
// mNode.disableNotification(mBattery);
// Features Audio Listner
if(mAudio!=null) {
mAudio.removeFeatureListener(mAudioListener);
mNode.disableNotification(mAudio);
}
if(mAudioSync!=null) {
mAudioSync.removeFeatureListener(mAudioSyncListener);
mNode.disableNotification(mAudioSync);
}
}`
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
GiovanniVisentiniST commentedon Jun 22, 2017
The node connection is done inside the NodeContainerFragment, so you can't be secure about when it starts and when the connection is done.
Are you secure that the node is connected when the onResume method is celled?
Try to implementa a logic like this one:
FeatureListActivity#onResume
Giovanni
cesarev91 commentedon Jun 23, 2017
Ciao Giovanni,
I tried how you told me and you were right the knot was not connected.
But now I have a problem with interacting more features on a single activity.
My layout is unique and is handled with a single activity on which I elaborate the data of all the feature. Microphone and Activity Recognition combined to return the animal's status. Battery to handle the battery of SensorTile and AudioADPCM and ADPCMSync to play audio.
I tried to keep the features to read the dog's status and it works, but trying to enable ADPCM audio also the node disconnects and the app crashes
Do you think it's a problem to handle everything on a single activity, or can you do it?
Cesare
GiovanniVisentiniST commentedon Jun 23, 2017
Ciao Cesare,
Do you have some error before the app crashes?
The possible problem could be that the audio transmit a lot of data and enabling also the other features could freeze the system.
Giovanni
cesarev91 commentedon Jun 23, 2017
I have to try to reactivate audio features and see if it hangs.
At the moment I'm trying to use microphone and activity in a combination and work, that is, they come into one of the conditions I've created and make a change of image. I've created two textview so you can read the event and the microphone level in real time. I do not understand why both of them are set continuously on ERROR (event) and -128 (level).
This is the code at the moment:
`public class MainActivity extends AppCompatActivity {
}`
GiovanniVisentiniST commentedon Jun 23, 2017
public void onUpdate(Feature f, Feature.Sample sample) {final FeatureActivity.ActivityType event = FeatureActivity.getActivityStatus(sample);final byte levelMic = FeatureMicLevel.getMicLevel(sample,1);I don't know it the problem is this, but for secure you can't call both the
getActivityStatusandgetMicLevelpassing the same sample object, because a sample contains the activity OR the micLevel..so one of the two call is giving you an error code..
Check the feature type using
instanceofor create 2 different listener.cesarev91 commentedon Jun 23, 2017
I tried with two different listeners and it works, there was also a mistake in getMicLevel (), it was put 0 in place of 1, so I can even read the microphone level and there is no more -128.
Then I also activated the whole part to handle the audio but unfortunately nothing works even if it does not hang up, just do not give me any data. I noticed that she does not enter the listener of the audio part. By activating only the audio part and disabling the dog's state, the audio is working.
I'm not sure but managing too much data in an activity brings the app into confusion.
What do you think about it?
Current code:
}
`
cesarev91 commentedon Jun 27, 2017
Ciao Giovanni,
I've changed the way I work, because managing a lot of data on a single activity does not allow the app to work
Now I'm using three activities and three layouts, I've also created an activity that shows the features (status, audio, battery).
ScanActivity -> FunctionActivity -> StatusActivity, AudioActivity, BatteryActivity
The app starts without errors but I do not receive any data.
This is the StatusActivity class:
`public class StatusActivity extends AppCompatActivity {
}
`
cesarev91 commentedon Jun 27, 2017
How do I keep the node connected during the operation of each activity?
GiovanniVisentiniST commentedon Jun 27, 2017
Note that if the node is already connected your activity will not work, since you will not receive the connection event.
Please see FeatureListActivity#onResume()
The connection is managed inside the NodeContainerFragment, to avoid to close it you have to call
mNodeContainer.keepConnectionOpen(true)before start the new activity this will avoid to disconnect the node when the fragment is destroyed
see:
FeatureListActivity#onOptionsItemSelected()
cesarev91 commentedon Jun 27, 2017
In the FunctionActivity class when I call other activities I use keepConnectionOpen (true)
This is the FunctionActivity class:
`public class FunctionsActivity extends AppCompatActivity {
`
GiovanniVisentiniST commentedon Jun 28, 2017
Usually you pass the current activity as a context, but anyway it seems ok, it is not working?
if the
keepConnectionOpenis not working please open a new issue..About your activity that doesn't receive data:
Since you split the activity and you have the same problem probably you don't have to much data, but you or the SDK are doing something wrong..
As already told the only weak point that I see is the
onResumefunction that will not enable the notification if the node connect before theonResumeis called.Try to isolate the problem, create an activity that only enable the micLevel, get it works, than add another feature..
maybe you can set a breakpoint into the BluetoothGattCallbacks object to follow all the low level BLE comunication..
cesarev91 commentedon Jun 28, 2017
Ciao Giovanni,
In the StatusActivity class, I inserted these two lines of code after instantiating mNode, which tell me if the node is connected:
Node.State state = mNode.getState ();
System.out.print ("Status:" + state);
The node is connected to the onCreate but I can not get into any of the listeners; the app starts without errors but does not show any data.
Now I will try to run MicLevel only.
cesarev91 commentedon Jun 28, 2017
I tried with this configuration and MicLevel works. But I do get a strange thing when I stop the app from android studio. To do this I need to unplug and reattach the SensorTile usb socket. If not, the app starts but does not show me any data and the SensorTile LED blinks mildly with respect to the first operation
}
`
cesarev91 commentedon Jun 28, 2017
Since every time I make changes I have several issues that do not match the question I asked about github so for any problem I should open a new discussion, if it is good for you to communicate directly in some way?
However, by adding the activity along with the microphone, the app detects both events, even though it sometimes disconnects and stops working.
GiovanniVisentiniST commentedon Jun 28, 2017
Don't worry open a new GitHub issue, its better have a public discussion to help also other people.
I'm reporting the problem with the Andrioid Studio to my colleges that develop the FW.
For your problem with the micLevel + activity try the example app and see if it happen also with that app.. I try and it works..
PS: your onResume method is still wrong..
cesarev91 commentedon Jun 28, 2017
Is it wrong to add listeners and enable notifications onResume?
In another version of my app I created an activity for each feature and onResume I did this and everything works.
I've always worked on the BlueSTExample module.
At the moment I'm working with both features (MicLevel + Activity) and work together. Problems remain the same: some disconnection during operation and when I stop the app from android studio I have to unplug the usb socket to reboot the app. This is the code:
}
`