2017년 3월 23일 목요일

Using the BLE Extension I want to access both characteristics of a Service


I am using AI2 with BLE extension to access BLE services on a BBC micro:bit.

The Button Service has 2 characteristics - Button A and Button B. Both return 0 = not pressed, 1 = short press, 2 = continuous or long press.

It's straightforward to create an App to read EITHER Button A OR Button B, but I can't see a way of being able to read the state of both buttons.

Can anyone help, please?

--
It seems to me that this is not possible. If you want both values returned together, then there must be a characteristic that provides this. This should be a string, I think. Can you create your own custom characteristic for the micro:bit? Otherwise you can maybe cannibalize one of the existing ones. In any case you must program something at the micro:bit side, AI can just try to make sense of what you send it.

--
I agree - It's not possible at the moment - I think it should be. There ought to be a way of linking a read command to a corresponding when changed or when read event, perhaps by allowing the embedded byte, or int, or string variable to be changed by the programmer?

Not feasible to to do anything on the micro:bit side.

-- 
This is a kind of philosophical problem. A characteristic is what programmers think of as an attribute. So reading a characteristic is the same as getting an attribute of some software object.
The problem comes from the notification of changes. And this would apply to any BLE device with several services and serveral characteristics for each, not just the micr:bit.
For the micro:bit, If you ask for the Accelerometer, magnetometer, button A, button B, IO-pins... How could any client, not just App Inventor, know what is being sent to it?
That said, at least for the buttons it would have been better if there was only one characteristic, which in its value would say which button is meant, not unlike the IO-pins, for which there is only one characteristic and for which io-pin-number, value pairs are sent.
-- 
I understand the point you are making, but there must be something extra at play which the BLE extension is not taking into account.

Martin Woolley has written two publicly available Apps to look at micro:bit BLE services:

microbit Blue, which allows each service to be looked at individually (if loaded in the micro:bit program, of course) With the button service it monitors BOTH buttons - ie two characteristics of one service - simultaneously, just like I am trying to do in AppInventor.

Bitty Datalogger monitors and records up to 3 Service/Characteristic pairs - temperature, accelerometer and magnetometer in NOTIFY mode. When the Appreceives data, how does it know which Service/Characteristic pair has sent it? Li9ke I said - there must be something else going on which BLE extension is missing.

I assume that Nordic's nRF Connect can do something similar, but I haven't tried it - I will, tomorrow - and report back.

-- 
This is important to find out! Is the source code also available?

--
I doubt if the source code for Martin Woolley's apps will be available.

However, as promised, I have checked the BBC micro:bit services  with nRF Connect, which has NO in-built knowledge of the BLE profile.

Here are my observations:

1.nRF connect sorts out which Characteristics belong to which Services - something I asked about in another thread - AI can't do this!
2. nRF can enably Notify on BOTH A and B Characteristics of the Button Service and report changes to both Button states correctly
3. nRF can enable Notify on Value Charactersitics of both Temperature Service and Accelerometer Service and report the values at the relevant Notify periods - 1000mS for temperature and 640mS for Accelerometer - I set these period values previously to simplify inspection of the nRF Connect Log File.

I think this demonstrates conclusively that AppInventor BLE extension is not doing everything it can and not fully utilising the capabilities of the Android BLE API.

I am attaching an extract from the nRF Connect log file


-- 
Thanks for this effort! I totally agree with you that work needs to be done on the BLE extension. I know the devolopers know, but I will try to add these specific points to their list.

-- 
FYI with some extremely tortuous AppInventor coding I have succeeded in correctly reading the Accelerometer data from the BBC micro:bit.
It requires 6 separate INT reads with offsets 0 to 5, little endian conversion and 2s complement arithmetic!!!
The 6 reads are a nightmare to program. However, at the moment the results are only meaningful the first time you access after starting the AI companion and it's so desperately slow as to be of little practical value!!

-- 
Neil, I heard that a new version including better support for this kind of thing will be available in about 2 months, with hopefully a beta version before that, so instead of torturing yourself, I hope you can have some patience. In any case you will have been instrumental in getting some of the improvements right.
--
There is a  great deal of satisfaction gained from solving each problem - whether caused by my own lack of knowledge, or the limitations of the AppInventor BLE extension.

Since I started my work on the BBC micro:bit, the limitations of the BLE extension  have forced me to explore coding techniques in AppInventor which I have never used before, and for that I am very grateful.

I will continue to explore!!!!!!!

It's not torture but a growth process!

I look forward to a new version and sincerely hope I can gain access to a Beta version.

-- 
I've added your name to the list of potential beta testers. I think we've addressed a lot of the challenges you been facing. We'll be reaching out once we're ready to start testing externally.

-- 
Thanks very much! Looking forward to starting!

Best wishes

-- 

Automatically submit with URL link already submitted form


I'm trying for days to find a way to automatically submit a form by clicking a URL. Without success.

I need this because I want the user of the form to maintain updated its form. When it receives an alert mail to tell him to keep it updated its form.

Currently, going on his form again and submitting it to Google Form timestamp updates.
But now I would like that the user does not go on his form and the form is submitted directly.

Do you know the syntax to do that with a URL that I can put in my email?

Thanks for your help

I begin to address on this site http://justingale.com/2013/09/url-tricks-for-google-forms-pre-populate-and-automatically-submitting-responses/ but it does not explain how to make an editable URL 

example :
https://docs.google.com/forms/d/1MgkHLgUvfOMsi9Db79ul6IvnZmNPmEhXKpllLoHAQTU/viewform?edit2=2_ABaOnufQOzSIi1XghOExwuRD9omS8nfb-Xqpz7-qliKfcA_C4QHvkP1DbGnn

--

How to Submitt Google form data to spread sheet using app inventor ?


I found it:
That is great and near to what i am looking for. I want to collects members data like name, email, phone, id card number, address etc to add into google form's spreadsheet. So is there a way i can implement any method to collect this data from users so they can enter and submit data so i can get it in my spread sheet? Hope you are getting me.

--
Isn't this precisely what my example does?

If you set up an AI2 app to collect the user data, this is then supplied to the google form and then committed to a spreadsheet (you do have to tell the google form to use a spreadsheet, though, check in "Responses")

--
Further to your posting here: Tim Carter's Images Listview

Please tell us which element of the process you need help with?

Creation of the google form, it's spreadsheet, and the deconstruction of the pre filled url for the form are really beyond the scope of this forum, but there is plenty you can simply google on for that.

If you follow my blocks in my original example you should see how to set up an AI2 app to submit a google form.

When/If you get stuck, come back here and ask, also with a screenshot of your relevant blocks.

--

Use AI2 to directly submit Google Form Data


This is possibly more of a Google thing than an Ai2 thing, but a neat trick nevertheless. My requirements are often solved by use of Google Forms, but they do not often present the best way for my users to enter data, and I prefer the flexibility of Ai2 to present a user interface. I came across a blog post by Justin Gale who had figured out how to automatically submit a Google form using pre-filled urls, and it crossed my mind that I could build the pre-filled url from data supplied in an AI2 app.

To begin, you will need to create your Google Form, which in turn will create the responses spreadsheet on Google Drive.

Here is a sample form, and the responses sheet that goes with it:



A normal prefilled url would look something like this:



Now to the app

Create an app with some list pickers that match the questions on the form. You can always do more code to automate this so that they link with the form. Also add a Web component


Next set up your blocks as in the following picture, building the Web1 url from the listpicker responses, and include a Web1.get call

You could work in a response if you needed confirmation, but it works without one.

To my mind this is a simpler method of collecting data and storing it in a spreadsheet than other methods I have used. It does rely on web connectivity, but you could use a tinydb to store the data until a connection is available.

aia attached :)


--

Tim Carter's Images Listview


Tim Carter shared the code for a listview on this thread.  His solution is the 3rd to last post on there.

Does you need Internet connection to use the listview?  Once the app is packaged, I mean?


--
don't get it!  I looked at the html file, and it's blank!  I tried putting the code from the 3rd post on this thread into the file and uploading the file to the project.  Then the images wouldn't show.

I need to edit myextn = ".png"; because I'd like to show images from the Internet, and images that are picked from the device with the activity starter.

I would like it to be able to display the pictures in a horizontal strip that you can scroll horizontally.

Are these things possible?  And if so, how do I do them?


-- 
My solution was for local use, so the html file expects to find the images in the same directory as itself.

You will need to include the full path / url in the html file in order to pull down images from the internet.

Suggest you include an internet check as well, for when it is not there!

You could try the php version I put up in my orogonal post, which was used to pull in the html file and images from a web server

-- 
Well, I did it.

Sorta.

I haven't tried putting an image file path through the Web Viewer.  (Would that work?)  I have edited your HTML code, though, so that it will display images from the web.  It works real nice.

The only thing is that there's this huge white space at the top of the Web Viewer.  How do I get rid of this?

And also, the WebViewString isn't being changed when an image is clicked.  How come?

This is the code I used:

<!DOCTYPE html>
<html>

<head>
 <meta name="author" content="puravidaapps.com">
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
 <script src="jquery-1.8.3.min.js"></script>
 <title>ImageView</title>

<style>
img {
    width:50px;
}
</style>

</head>

<body>

  <script>
  $(document).ready(function() {
 
    var webString = window.AppInventor.getWebViewString().split(",");
    $.each( webString, function( index, val ) {
            myval = "\'"+val+"\'";
            $("body").append($( '<a href="javascript:;"><img src='+ val + ' onclick="window.AppInventor.setWebViewString('+ myval +')"></a>' ));
        });
    });

  </script>

</body>

</html>


-- 
Suggest you revisit my original code and put the url to the folder with the images in it into the html page rather than feeding it to the script:


Might take a little bit of fiddling with the code here to get the syntax right.
And then make sure you recheck the blocks to ensure the list of images is just the filename without the extension [apple,bike,bed]

Am guessing the big white space is failed images? I only see a white webviewer before I click on the Home button to load the html page? There is nothing in the html to create the white space so it must be coming from the script?

-- 
Good idea!

Failed images sounds about right!  There's even a broken image icon.

One pondering: Mightn't it be simpler just to enter the whole file names?  Especially if they have different extensions...

-- 
Get it working first, then we can look at different file types, although for simplicity some commonality of file type would be easier to manage!

Use imagemagick: convert -format png *.jpg


--
I would do that (the second part, about commonality of file type), but this program lets the user upload their own files.

So, I've been fiddling.

I don't have an online URL to a folder of images because the user is allowed to add and remove images.  I tried setting the src to the file's name.  The screen was blank.  So I still have it pulling images straight from the web.

I used styling in the HTML to take care of the spaces.  Well, I'm working on that, but I have the basic concept, even if I don't have the exact numbers of pixels.

The only thing that isn't working in the onClick function setting the webViewString, which is an essential part of the program.  I did the code at bottom to see if the onClick function is being called (it is).  The code sets the text of the paragraph with the id "my-paragraph" to "Hello!" when an image is clicked.

But webViewString isn't being changed.  At least, I don't think it is.  The code I have for the setting of Label1 is attached.

I have another question.  I want the user of my program to be able to set the width or height of the images in the viewer.  Could that be done?  I'd have to set the html file's styling text, and I don't think that would work because of something I accidentally found out earlier.

Anyways, the code I promised is below:

<!DOCTYPE html>
<html>

<head>
 <meta name="author" content="puravidaapps.com">
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
 <script src="jquery-1.8.3.min.js"></script>
 <title>ImageView</title>

<style>
img {
    width:100px;
    margin:-2px;
    padding:0px;
}
body {
    margin:0px;
    margin-top:-22px;
    padding:0px;
}
</style>

</head>

<body>

<p id="my-paragraph"></p>

  <script>
  $(document).ready(function() {
    var webString = appInventorText.split(",");
    $.each( webString, function( index, val ) {
            $("body").append($( '<a href="javascript:;"><img src='+ val +' onClick="document.getElementById(\'my-paragraph\').innerHTML=\'Hello!\'"></a>' ));

        
        });
    });

  </script>

</body>

</html>

   
        

-- 
Took me two days of iterating changes until I found my original solution, so suggest you focus on the syntax in the javascript until it starts producing output

-- 
Alright, I'll try.  Do you mean by syntax I'm using the wrong function or I didn't type something right?  I looked up the word and got more confused.

--
Build bit by bit. For example, this works:



<!DOCTYPE html>

<html>

<head>
 <meta name="author" content="puravidaapps.com">
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
 <script src="jquery-1.8.3.min.js"></script>
 <title>ImageView</title>

<style>
img {
    width:100px;
    margin:0px;
    padding:0px;
}
body {
    margin:0px;
    margin-top:0px;
    padding:10px;
}
</style>
</head>

<body>

<p id="my-paragraph"></p>

<a href="javascript:;"><img src='dolphin.jpg' onClick=document.getElementById('my-paragraph').innerHTML='Hello!'></a>

</body>

</html>

but you want the setwebviewstring so build from here?

EDIT

Just seen your other post:

https://groups.google.com/forum/#!category-topic/mitappinventortest/kxrdu8tEzgA


There is either an issue with your blocks (e.g. in my example the clock only fires its code when there is a match) or with the html. Are your blocks very different to my example? If so post and image so others can see what is going on. Where is the "user" uploading their files to? how are you getting a url for those files? You have posted your html, but just in case it may be worth posting what you think should work, then we can take it from there. I can't test your html as i do not know how you have the urls set up for the images.



-- 
1. Yes, my blocks are different from your example, but the concepts are still the same: Set WebViewString to the images we want.  Yours gives the names of the image without their ".png" extension.  But mine sets the WebViewString to the full URL or full filepath.  Also, mine does not clear the cash, but having it doesn't fix anything.
2. The image isn't really being uploaded.  The user selects an image using ActivityStarter, which fires up the file manager.  When the user selects an image, the URI is returned in the AfterActivity handler.  The user gives the image an original name, via the notifier's ShowTextDialog.  Then the appadds the image's filepath to a variable that stores all the filepaths/URLs.  Also, the app adds the image's name to a variable that stores all the names.
3. About how I set up the URLs: I have (as an asset) a file of names and (online) image URLs.  The user selects the names of the images to display.  Every time an image is added or removed from the images currently shown, the WebViewer is refreshed.

And for anyone who's wondering what I've tried: I have tried a different jQuery method of creating the image elements (var myElement = $("<img>")) and settings their attributes (myElement.attr("src", val)).  I have also tried using HTML instead of jQuery, since I eventually want to get away from jQuery (that didn't work at all).






ImageView.aia

-- 
I had a thought today.

What if our problemo isn't the code, but the jQuery file?  What does the code in the jQuery file allow?  Can you do all jQuery methods etc with that one file, or do you have to download the full file?  Is it the full file that's you already have in the project?

-- 
It is not the jQuery file.

But try this:



<!DOCTYPE html>

<html>

<head>
 <meta name="author" content="puravidaapps.com">
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
 <script src="jquery-1.8.3.min.js"></script>
 <title>ImageView</title>

<style>
img {
    width:100px;
    margin:0px;
    padding:0px;
}
body {
    margin:0px;
    margin-top:0px;
    padding:10px;
}

</style>
</head>

<body>

<p id="my-paragraph"></p>

<div>
<img id='image_id' src='dolphin.jpg'>
<img id='image_id' src='bear.jpg'>
<img id='image_id' src='tiger.jpg'>
</div>
<script>
$('img').click(function(){ 
document.getElementById('my-paragraph').innerHTML=$(this).attr('src'); 
});
</script>

</body>

</html>

with the attached image files.

On clicking an image, the src of the the image is returned to "my-paragraph". (you will only get the file name as they are local). With a bit of work, i don't see why the setwebviewstring won't pick this up ?

Note; the script has to be below everything else on the html page
REF: https://api.jquery.com/click/




-- 
I'm trying to try it.
1. I downloaded your original aia file and opened it in app inventor.
2. I deleted the Web1 component, and deleted the ClearCache block, since I don't see those doing anything.
3. Then I edited the program to work with the file.  (I also pasted your code into a text block in the code since that'll make it easier to edit the code.)
4. I viewed it with the companion app.  The images aren't showing.  I took a screenshot (attached).  I'm also including a screenshot of the blocks and designer.

I probably did something really silly and can't see it.  Do you my mistake?
Edited

P.S. I tried adding ClearCache back in, and brought back the Web1 component.  Nada.





-- 
This simple example shows the javascript being fed back to the webviewstring property. Seems you need a "get" to make the "set" work!



<!DOCTYPE html>

<html>

<head>
 <meta name="author" content="puravidaapps.com">
 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
 <script src="jquery-1.8.3.min.js"></script>
 <title>ImageView</title>

<style>
img {
    width:75px;
    margin:0px;
    padding:0px;
}
body {
    margin:0px;
    margin-top:0px;
    padding:10px;
}

</style>
</head>

<body>

<p id="mylabel"></p>

<div>
<img id='image_id' src='dolphin.jpg'>
<img id='image_id' src='bear.jpg'>
<img id='image_id' src='tiger.jpg'>
</div>
<script>
$('img').click(function(){ 
document.getElementById('mylabel').innerHTML=$(this).attr('src');
window.AppInventor.getWebViewString();
          window.AppInventor.setWebViewString($(this).attr('src'));
});
</script>


</body>

</html>

testurlimageview.aia

-- 
Hi Tim
How are you. 

i found your post Use AI2 to directly submit Google Form Data and this what i was looking since long time.

That post is closed for replies so i am asking you here. I want to make user data collection app.
Like.

Name"
email :
Nic#:
Cell Number 
Address :

and some more text fields. So when user will fill the google from via app and click submit it should collected via response sheet as you did in that post.

Can you help me with this? 
I really need this.
Thank you in advance.

-- 
Please don't cross post like this, get's very confusing!

I have, and will again respond to your query here:


--