-
• #2
I have mange to work and took an working example from here:
https://www.espruino.com/BLE+Communicationsthis is the code I have wrote:
My_MAC = NRF.getAddress(); print("My MAC address is " , My_MAC); var n = "0"; NRF.setServices({ "3e440001-f5bb-357d-719d-179272e4d4d9": { "3e440002-f5bb-357d-719d-179272e4d4d9": { writable : true, onWrite : function(evt) { n = evt.data[0]; if (n < 18) { digitalWrite(LED, 1); } else { digitalWrite(LED, 0);} } }, "3e440003-f5bb-357d-719d-179272e4d4d9": { readable : true, value : [getTime()] } } }, {}); // On disconnect, turn off led NRF.on('disconnect', function() { digitalWrite(LED, 0); }); NRF.setAdvertising({}, {name:"Test_Read_Write"});
when I connect using android phone "nRF Connect "
I can see I have 2 chars from 1 service
3e440002 is write
3e440003 is readI have 3 questions :
when I connect to the 3e440002 - and send any byte - LED is on (which is good for me to understand how things works )
when I connect to 3e440003 - he only show me "4C 'L'"- what do I need to do in order to see "live" data (timestamp - just to see it's alive), or even the latest byte I sent to the device?
- is there any to see console.print while I'm connecting using web ide on my computer?
or do I have to connect it using serial cables? when I use a python code to send data I get this error:
Characteristic 3e440002-f5bb-357d-719d-179272e4d4d9 does not support write operations!
when I use the same code to connect to Arduino with the same chars - I can send data to it ,
also as I mention before - on android nRF I can send messagesso what am I missing ?
Thanks ,
- what do I need to do in order to see "live" data (timestamp - just to see it's alive), or even the latest byte I sent to the device?
-
• #3
Hi - sorry for the delay, I was away last week...
so the PI is the client and the MDBT42Q will be the server , right ?
Usually, yes. Although the opposite is possible.
what is the approximately~ distance I can use for communication ?
Realistically around 10M
can I connect an external antenna to the MDBT42Q and see if it's make any changes?
Not easily on the normal board, but we do sell some where this is possible: https://shop.espruino.com/mdbt42q/mdbt42q-breakout-ufl
I have a working code on Arduino BLE( my problem with the Arduino is the distance , I get around ~ 4 meters only ), can I publish the code here and get some help converting it to java?
Yes, that's fine.
what do I need to do in order to see "live" data (timestamp - just to see it's alive), or even the latest byte I sent to the device?
NRF.setServices
only sets the value of data at that point. To update the value that is available you need to keep callingupdateServices
when the data changes. There is an example at http://www.espruino.com/Reference#l_NRF_updateServicesis there any to see console.print while I'm connecting using web ide on my computer?
If you're connected to the same computer you can sometimes use the IDE and python code at the same time (but not different computers).
Otherwise yes, you'd have to use a serial cable.
when I use a python code to send data I get this error: Characteristic 3e440002-f5bb-357d-719d-179272e4d4d9 does not support write operations!
Can you write to it using an app like NRF Connect on your phone? it would help to rule out any issue with the Pi.
Hope that helps!
-
• #4
first of all
thank you fir the help so far , you don't need to apologize :-)this is what I have now :
- created a device called "Test_Read_Write" - I can see it on BLE Scan
- I have open "nRf" on by Android device and mange to connect to it .
sending < 18 - led is on , > 18 led is off - so communication is working. I'm trying to add update service , did I do it right ?
I can see the data is changing when I send something to the device
but is there a function I can call to update the value only after the data is change?
and not print it once every 1000mSec (like I did)?
it will be better no ?My_MAC = NRF.getAddress(); print("My MAC address is " , My_MAC); var n = 0; NRF.setAdvertising({}, {name:"Test_Read_Write1"}); NRF.setServices({ "3e440001-f5bb-357d-719d-179272e4d4d9": { "3e440002-f5bb-357d-719d-179272e4d4d9": { writable : true, maxLen : 5, onWrite : function(evt) { n = evt.data[0]; if (n < 18) { digitalWrite(LED, 1); } else { digitalWrite(LED, 0);} } }, "3e440003-f5bb-357d-719d-179272e4d4d9": { readable : true, notify: true, value : ["hello"] } } }, {}); setInterval(function() { NRF.updateServices({ "3e440001-f5bb-357d-719d-179272e4d4d9" : { "3e440003-f5bb-357d-719d-179272e4d4d9" : { value : [n], notify: true } } }); }, 1000); // On disconnect, turn off led NRF.on('disconnect', function() { digitalWrite(LED, 0); });
when I upload the code I see this error :
BLE Connected, queueing BLE restart for later Uncaught Error: Can't update services until BLE restart at line 37 col 2 in .bootcde
is this OK ? or does it mean I have a problem ?
***after I will see everything is working on with my phone , I will need your help with the python error of sending data
Thanks ,
- created a device called "Test_Read_Write" - I can see it on BLE Scan
-
• #5
Great, this looks good!
I can see the data is changing when I send something to the device but is there a function I can call to update the value only after the data is change? and not print it once every 1000mSec (like I did)?
There's nothing built in (often you may want to be able to send the same number twice). But it's easy enough for you to add code like
if (value!=lastValue) ...
.BLE Connected, queueing BLE restart for later
No, this is fine. It just means that Espruino can't change the advertised services when you're connected to it. The second you disconnect it'll change them and all will be fine
-
• #6
Ok
so we are on the right way :-)security question (before I continue with the python)
is there any way I can secure the connection ?
I will explain
right now
if someone will take a computer and run "Espruino Web IDE", scan - he will see my device.
and then he will be able to connect to him and do what evert he want - right?
(the same way I'm running now and uploading the code).
How can I make him request password before connecting ?and another question
can I use this security (password) in order to connect to the device and read the data ?
I want only verified devices to be able to read the Espruino data
right now any one can connect and readThanks,
-
• #7
https://www.espruino.com/BLE+Security
for me it was enough to have this code to disconnect unknown devices and learn new ones when holding button as per "Disconnect when an unknown address is found (whitelisting)" chapter in that guide
NRF.whitelist=[]; NRF.on('connect',function(addr) { if (!NRF.whitelist.includes(addr)){ if (BTN1.read()){ // add to whitelist when button is held while connecting NRF.whitelist.push(addr); //vibrate(1,1,100,0); } else NRF.disconnect(); } });
-
• #8
OK - nice solution ,
and this is better then solution then a password?also what will happened when someone will try to connect using the IDE and upload new code?
-
• #9
and this is better then solution then a password?
password does not close the connection, it protects only console not other services
what will happened when someone will try to connect using the IDE and upload new code
you cannot connect via IDE when the device is not in the list, every connection from unknown devices is disconnected
-
• #10
Ok I will try it today ,
some more "basic" questions
- I'm trying to change the description of the UUID, but I get unknown all the time
I want to send the temperature - but when I read I get "1D" - what do I need to change so it will know it's temperature value and now byte data?
NRF.setServices({ "3e440001-f5bb-357d-719d-179272e4d4d9": { "3e440002-f5bb-357d-719d-179272e4d4d9": { description: "My_LED_UUID", // optional, default is null, writable : true, readable : true, notify: true, maxLen : 10, value : "Setup_Data", onWrite : function(evt) { data = evt.data[0]; if (data < 18) { digitalWrite(LED, 1); digitalWrite(Relay_Pin, 1); } else { digitalWrite(LED, 0); digitalWrite(Relay_Pin, 0);} } }, "3e440008-f5bb-357d-719d-179272e4d4d9": { description: "Device_Temp", // optional, default is null, readable : true, notify: true, value : [E.getTemperature()] } } }, {}); setInterval(function() { NRF.updateServices({ "3e440001-f5bb-357d-719d-179272e4d4d9" : { "3e440002-f5bb-357d-719d-179272e4d4d9" : { value : [data],//to be able to see that read is correct notify: true }, "3e440008-f5bb-357d-719d-179272e4d4d9" : { value : [E.getTemperature()],//to be able to see that read is correct notify: true } } }); }, 5000);
what am I missing?
Thanks ,
- I'm trying to change the description of the UUID, but I get unknown all the time
-
• #11
I think the code you have there for the temperature is fine...
0x1D is hex for 29, which sounds like a reasonable number for temperature.
I'm not entirely sure about the description. How are you reading it? On the whole the description isn't a very useful value as no software ever really looks at it though
-
• #12
so 3.5 questions about it :
- I guess I need to convert the 0x1D to 29 using some java hex to DEC function ?
- I'm trying to read it using nRF , as I understand from the API Reference
> NRF.setServices({ 0xBCDE : {
> 0xABCD : {
> value : "Hello", // optional
> description: "My Characteristic", // optional, default is null,
I thought maybe I can write something there - but if it's no used , so never mind.
what is 'heartrate' mean in the value section ?
NRF.setServices({ 0x180D: { // heart_rate 0x2A37: { // heart_rate_measurement notify: true, value : [0x06, heartrate], } } }, { advertise: [ '180D' ] });
does it tell that the data is bpm ? - if I'm correct :
where can I find a list of what I can put \ which values?can I say I'm sending temperature using
value = [0x1d, temperature]
then when I will read the data it will change it to C and I will see 29 ?
3.5 what will be if I'm sending heartrate using my own UUID ?
Thanks ,
- I guess I need to convert the 0x1D to 29 using some java hex to DEC function ?
-
• #13
I guess I need to convert the 0x1D to 29 using some java hex to DEC function ?
No... it's just the way that nRF connect is showing you the number I think. In reality in whatever variable you're using it's just a number like any other
description: "My Characteristic", // optional, default is null
I thought maybe I can write something there - but if it's no used , so never mind.Yes, the description has no effect on the functioning of your code
what is 'heartrate' mean in the value section ?
That would be a variable that would contain the heart rate as a number. Like maybe 85 (eg 85 bpm).
where can I find a list of what I can put \ which values?
You just have to look it up online - the Bluetooth SIG used to have a webpage showing them but they've made them a bit tricky to find now.
You can just make your own UUIDs though for whatever you want to send, then it's up to you to interpret the result. Maybe check out https://www.espruino.com/About+Bluetooth+LE
-
• #14
when I print to the OLED
E.getTemperature() - I get 24.5 , so it's OK
so if I will use this Characteristic for the temperature '2A6E' - will it show me ok on the nRF?
I have looked here
https://programmaticponderings.com/2020/08/04/getting-started-with-bluetooth-low-energy-ble-and-generic-attribute-profile-gatt-specification-for-iot/and you can see in the nRf he is showing decimal value and say it's temp
https://programmaticponderings.files.wordpress.com/2020/08/screenshot_20200731-185558-5.pngI guess I will need to change the UUID also , no ?
Thanks ,
About my code
- can I see the MAC of the remote device that connected?
I want to print it on the OLED , for testing I have wrote this code , it's seem to be working,
my problem is when I disconnect:
LED2 is off (as it should be)
but on the OLED I still see "Connected" and the temp is changing every 5 seconds
I guess it's because the Interval function that is still running
can you see what I did wrong?My_MAC = NRF.getAddress(); Relay_Pin = 22; print("My MAC address is " , My_MAC); var n = 0; function start(){ // write some text g.setFontVector (20); g.drawString("David Test!",2,2); g.drawString("BLE ON",2,40); // write to the screen g.flip(); } function BLE_Connect(){ setInterval(function() { NRF.updateServices({ "3e440001-f5bb-357d-719d-179272e4d4d9" : { "3e440008-f5bb-357d-719d-179272e4d4d9" : { value : [E.getTemperature()],//to be able to see that read is correct notify: true } } }); g.clear(); g.setFontVector (20); g.drawString("Connected!",2,2); g.setFontVector (10); g.drawString("Temp is: " + E.getTemperature(), 1, 40); g.flip(); }, 5000); } function BLE_Disconnect(){ g.clear(); g.setFontVector (20); g.drawString("Waiting!",2,2); g.flip(); } var i2c = new I2C(); i2c.setup({ scl : D20, sda: D19 }); var g = require("SSD1306").connect(i2c, start); NRF.setAdvertising({}, {name:"OfficeTest"}); NRF.setServices({ "3e440001-f5bb-357d-719d-179272e4d4d9": { "3e440002-f5bb-357d-719d-179272e4d4d9": { description: "Setup Led", // optional, default is null, writable : true, readable : true, notify: true, maxLen : 10, value : "Setup_Data", onWrite : function(evt) { data = evt.data[0]; if (data < 18) { digitalWrite(LED, 1); digitalWrite(Relay_Pin, 1); } else { digitalWrite(LED, 0); digitalWrite(Relay_Pin, 0);} } }, "3e440008-f5bb-357d-719d-179272e4d4d9": { description: "Device Temp", // optional, default is null, readable : true, notify: true, value : ["Temp_Location"] } } }, {}); setInterval(function() { NRF.updateServices({ "3e440001-f5bb-357d-719d-179272e4d4d9" : { "3e440002-f5bb-357d-719d-179272e4d4d9" : { value : [data, heartrate],//to be able to see that read is correct notify: true }, } }); }, 5000); // On disconnect, turn off led NRF.on('disconnect', function() { digitalWrite(LED2, 0); BLE_Disconnect(); }); NRF.on('connect', function() { digitalWrite(LED2, 1); BLE_Connect(); });
Thank you again ,
- can I see the MAC of the remote device that connected?
-
• #15
but on the OLED I still see "Connected" and the temp is changing every 5 seconds. I guess it's because the Interval function that is still running
Yes... so in
BLE_Connect
you callsetInterval
but you never clear that interval.Try:
var updateInterval; function BLE_Connect(){ updateInterval = setInterval(function() { .... } function BLE_Disconnect(){ if (updateInterval) clearInterval(updateInterval); updateInterval=undefined; ... }
-
• #16
Ok, it's working - thank you!
but now I see another problem ,
when I try to read the pin status using this command:NRF.setServices({ "3e440001-f5bb-357d-719d-179272e4d4d9": { "3e440002-f5bb-357d-719d-179272e4d4d9": { description: "Setup Led", // optional, default is null, writable : true, readable : true, notify: true, maxLen : 10, value : "Setup_Data", onWrite : function(evt) { data = evt.data[0]; g.clear(); g.setFontVector (20); g.drawString('Data receive',2,2); g.drawString(data,2,40); g.flip(); if (data =="1") { // if (data < 18) { digitalWrite(LED, 1); digitalWrite(Relay_Pin, 1); } else { digitalWrite(LED, 0); digitalWrite(Relay_Pin, 0);} Relay_Status = digitalRead(Relay_Pin); } }, "3e440008-f5bb-357d-719d-179272e4d4d9": { description: "Device Temp", // optional, default is null, readable : true, notify: true, value : [E.getTemperature()] } } }, {});
it turn off the led that connected to Relay_Pin
when I remove the this line - the led stay on
what could be the problem ?
when I read the data from "nRF" I can see the value is "0x01"and one final "understanding" question:
if I understand correct - there is no need for the connected device to know the Service UUID , just the CHAR uuid
there is no used of the service - right ?***I mange to make my Python code work - and there I only used the CHAR UUID , didn't use \ took any attention for the Service UUID
-
• #17
Reading the status of the pin turns it into an input. You can force it with
pinMode(Relay_pin,"output")
but honestly I'd just store the current status of the pin in a variable - it's much easier.Reading pin state isn't as easy as you'd think - if the pin was shorted then reading the value would always return 0 even though you might have set the output to 1
-
• #18
so I can't read the pin status and know if it's "1" \ "0"?
-
• #19
Not reliably because you're reading the voltage on the pin, NOT what you set the pin to.
-
• #20
Ok
Thanksit seem that now everything is working for me (almost),
I will continue working - and if I will have more question I will ask.Thank you very much for the help!
Hello,
I have a simple project I want to run and want to know if I can use the MDBT42Q
I want to see I understand the configuration correct:
so the PI is the client and the MDBT42Q will be the server , right ?
Thanks,