-
• #2
I haven't used the hub stuff, but will that not work for you?
To interact with a Puck you fundamentally only need a BLE library in the language you are most familiar with. With that you can connect to and use the pucks built in UART service.
I think in Node the common one is Noble, but with any library you'd have to write code. I used a BLE library for Go sometime back and added an abstraction layer for Puck commands, including the ability to call functions. It works and might do what you need.
Another option is of course, Web Bluetooth.
-
• #3
any recommendation for python. all i wish to do is to send a command i.e.
Puck.IR(require("pronto").decode("0000 006D 0000 0082 007D 003F 0010 0010 0010 0010 0010 002F 0010 0010 0010 002F 0010 0010 0010 0010 0010 0010 0010 002F 0010 002F 0010 0010 0010 0010 0010 0010 0010 002F 0010 002F 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 002F 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 002F 0010 0010 0010 0010 0010 0010 0010 0010 0010 002F 0010 002F 0010 002F 0010 002F 0010 002F 0010 002F 0010 002F 0010 002F 0010 0010 0010 0010 0010 002F 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 002F 0010 002F 0010 0010 0010 0010 0010 002F 0010 0010 0010 0010 0010 0010 0010 002F 0010 0010 0010 002F 0010 0010 0010 002F 0010 0010 0010 0010 0010 0010 0010 002F 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 002F 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 002F 0010 0010 0010 0010 0010 0010 0010 002F 0010 0010 0010 002F 0010 0010 0010 0010 0010 002F 0010 0010 0010 003F"));
-
• #4
what would be the connection speed i need to set up
-
• #5
i am trying the following, but i get following error. any help please
Traceback (most recent call last): File "puck_serial.py", line 6, in
sock.connect((bd_addr,port)) File "<string>", line 5, in connect bluetooth.btcommon.BluetoothError: (112, 'Host is down')
from bluetooth import * import time bd_addr = "D8:19:E7:5B:3A:57" port = 1 sock = BluetoothSocket (RFCOMM) sock.connect((bd_addr,port)) print 'waiting' while 1: data = sock.recv(10) print data time.sleep(2.0) [#tosend](https://forum.espruino.com/search/?q=%23tosend) = raw_input() [#if](https://forum.espruino.com/search/?q=%23if) tosend != 'q': # sock.send(tosend) [#else](https://forum.espruino.com/search/?q=%23else): # break sock.close()
-
• #6
what would be the connection speed i need to set up
You shouldn't need one at all - connection speed doesn't really apply for something like Bluetooth LE.
You could look at using
bluepy
for Python: https://github.com/IanHarvey/bluepyHowever if you're ok with JS then Noble for Node.js is probably one of the most stable BLE libraries out there. You could even use the code that the Espruino CLI tools use as a base: https://github.com/espruino/EspruinoTools/blob/gh-pages/core/serial_noble.js
But at the end of the day you need to:
- Find and connect to the device
- Find the service
6e400001b5a3f393e0a9e50e24dcca9e
- Find the characteristic
6e400002b5a3f393e0a9e50e24dcca9e
on that service - Write your data to it in chunks of 20 bytes at a time.
But if you just want an easy time of it, install EspruinoHub and then send an MQTT message containing your JS command to
/ble/write/DEVICE_ADDRESS/nus/nus_tx
- Find and connect to the device
-
• #7
Looks like I posted my reply before I saw your last post.
In your last post, you're using the
bluetooth
library. That's for standard Bluetooth (eg. Bluetooth 2), and not Bluetooth LE - so it won't work here.You'll need to use
bluepy
or one of the other Python Bluetooth LE implementations -
• #8
Adafruit have a Python library for their Bluefruit stuff that may work for you: https://github.com/adafruit/Adafruit_Python_BluefruitLE/blob/master/examples/low_level.py
But basically it looks like there's very little code out there for doing this on Python so you're making your life quite difficult. By contrast there's quite a lot of Node.js stuff.
This example came up: https://github.com/tigoe/BluetoothLE-Examples/tree/master/noble/readSerial
Or there's even this library https://www.npmjs.com/package/node-uartble
-
• #9
Ok, I just created an example for you that should work:
# based on https://github.com/rlangoy/bluepy_examples_nRF51822_mbed/blob/master/writeLed2.py import sys from bluepy.btle import UUID, Peripheral if len(sys.argv) != 2: print "Fatal, must pass device address:", sys.argv[0], "<device address="">" quit() p = Peripheral(sys.argv[1], "random") UartService=p.getServiceByUUID(UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")) ch = UartService.getCharacteristics(UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"))[0] # \x03 -> Ctrl-C clears line # \x10 -> Echo off for line so don't try and send any text back ch.write("\x03\x10LED.toggle()\n"); p.disconnect()
In your case the text you want to write will be more than 20 characters, so you'll need to write it in 20 character chunks
-
• #10
Ok, or code that actually does the splitting for you:
# based on https://github.com/rlangoy/bluepy_examples_nRF51822_mbed/blob/master/writeLed2.py import sys from bluepy.btle import UUID, Peripheral if len(sys.argv) != 2: print "Fatal, must pass device address:", sys.argv[0], "<device address="">" quit() # \x03 -> Ctrl-C clears line # \x10 -> Echo off for line so don't try and send any text back # command = "\x03\x10reset()\nLED.toggle()\n" command = "\x03\x10clearInterval()\n\x10setInterval(function() {LED.toggle()}, 500);\n" p = Peripheral(sys.argv[1], "random") UartService=p.getServiceByUUID(UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")) ch = UartService.getCharacteristics(UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"))[0] while len(command)>0: ch.write(command[0:20]); command = command[20:]; p.disconnect()
-
• #11
Amazing, saved me a heap of testing.
i get an error with your code
python puck_serial.py D8:19:E7:5B:3A:57
> Traceback (most recent call last): File "puck_serial.py", line 13, > in <module> > p = Peripheral(sys.argv[1], "random") File "/usr/local/lib/python2.7/dist-packages/bluepy/btle.py", line 391, in > __init__ > self._connect(deviceAddr, addrType, iface) File "/usr/local/lib/python2.7/dist-packages/bluepy/btle.py", line 439, in > _connect > raise BTLEDisconnectError("Failed to connect to peripheral %s, addr type: %s" % (addr, addrType), rsp) > bluepy.btle.BTLEDisconnectError: Failed to connect to peripheral > D8:19:E7:5B:3A:57, addr type: random
-
• #12
i noticed that when i try to run the code above, and then seperatly on another computer try to connect to the puck.js through the web console, that it no longer is found, only when i remove the battery, then i can find it on the web console. maybe the connection from the python code is not negociating properly
-
• #13
That's odd - only difference I can see is when I used it, I typed in a lowercase address. Could you try that?
In https://github.com/rlangoy/bluepy_examples_nRF51822_mbed/blob/master/writeLed2.py that I based it on there's a try...finally for disconnection but the exception that's reported is from earlier in the code, so that wouldn't have caused an issue.
You could also try
sudo /etc/init.d/bluetooth restart
at the console which should restart the Bluetooth service and would automatically disconnect if it has stayed connected to the device for some reason. -
• #14
the restarting of the bluetooth seems to release the connection, and hence able to find in the web console. but the lower case didn't fix the isse
-
• #15
Just a thought - maybe obvious to OP, maybe not. Rather than sending long commands and splitting, could wrap the control commands in functions and send to Puck from IDE and
save()
to flash. Then just callload()
from flash in the control application and call the functions. This would keep the code in the control application manageable. I'm assuming they will all fit in Puck flash which may not be case though?If anybody else uses Golang and Puck, this is the library I referred to. Tested on Mac and Raspberry Pi and I've had some joy with it.
-
• #16
from debugging, the python script does not go past
p = Peripheral(sys.argv[1], 'random')
-
• #17
Maybe check that you have the latest
bluepy
and that nothing else is running (eg EspruinoHub) that might be using Bluetooth. And is the Puck's firmware up to date?If so, I think your best bet is to post on bluepy's GitHub issue tracker and see they can help figure it out
-
• #18
i managed to get the serial working on another RPI, how could i call a function within the puck please
-
• #19
Literally just change the python
command
variable to:command = "\x03\x10yourFunctionName();\n"
Apart from the first 2 chars you're just sending JS, so if you want to send arguments it's as easy as
"\x03\x10yourFunctionName(1,2,3,'foobar');\n"
-
• #20
Thanks Gordon,
i am using the following function on the puck, and ideally i would like to return something back to my python script. i.e temperature value.
function beam(ircode) { Puck.IR(require("pronto").decode(ircode)); return "test"; }
see below my python code as wel. i am so far getting the following value back from the puck, or is it not from the puck hhh
response value beam(sleep);
import sys from bluepy.btle import UUID, Peripheral import time import binascii command = "\x03\x10beam(" +sys.argv[2]+ ");\n" p = Peripheral(sys.argv[1], 'random') try: UartService=p.getServiceByUUID(UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")) ch = UartService.getCharacteristics(UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"))[0] while len(command)>0: ch.write(command[0:20]); command = command[20:]; time.sleep(1.0) # Allow sensor to stabilise [#uuidValue](https://forum.espruino.com/search/?q=%23uuidValue) = btle.UUID("f000aa71-0451-4000-b000-000000000000") [#lightSensorValue](https://forum.espruino.com/search/?q=%23lightSensorValue) = lightService.getCharacteristics(uuidValue)[0] val = ch.read() print "response value", val p.disconnect() finally: p.disconnect()
-
• #21
For receive you need the
"6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
characteristic (there's one for transmit which we're using, and one for receive) - so you may have more luck withrx = UartService.getCharacteristics(UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"))[0]
andrx.read();
.However, the best way to get data back from the Puck is to use notifications - but you'll have to find an example of how to do that with
bluepy
-
• #22
Thanks
this is such an example, so i need to setup anything on the puck.js side?
while True:
if p.waitForNotifications(1.0): print("Notification trigger") continue print("Waiting")
is
return E.getTemperature();
sufficient
-
• #23
This my code so far on the puck , and I am able to connect using the python code below and send commands, but I am unable to return a value back, actually I do receive something, such as
<type 'str'> <- Serial1 >
but it should be temperature reading of the puck. any help please
Puck Code:
function beam(ircode) { Puck.IR(require("pronto").decode(ircode)); digitalWrite(LED2,1); setTimeout(function() { digitalWrite(LED2,0); }, delayInMilliseconds); return E.getTemperature(); }
Python:
import sys from bluepy.btle import UUID, Peripheral import time import binascii from bluepy import btle command = "\x03\x10beam(" +sys.argv[2]+ ");\n" class MyDelegate(btle.DefaultDelegate): def __init__(self): btle.DefaultDelegate.__init__(self) def handleNotification(self, cHandle, data): print("A notification was received: %s" %data) p = Peripheral(sys.argv[1], 'random') p.setDelegate(MyDelegate()) try: UartService=p.getServiceByUUID(UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")) ch = UartService.getCharacteristics(UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"))[0] while len(command)>0: ch.write(command[0:20]); command = command[20:]; p.writeCharacteristic(ch.valHandle+1, "\x02\x00") while True: if p.waitForNotifications(1.0): # handleNotification() was called continue print("Waiting...") # Perhaps do something else here [#rx](https://forum.espruino.com/search/?q=%23rx) = UartService.getCharacteristics(UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"))[0] [#val](https://forum.espruino.com/search/?q=%23val) = rx.read() [#print](https://forum.espruino.com/search/?q=%23print) val p.disconnect() finally: p.disconnect()
-
• #24
Looks promising.
I'd suggest changing
command
to:command = "\x03\x10Bluetooth.println(beam(" +sys.argv[2]+ "));\n"
What's happening is, as mentioned in the code I posted,
\x10 -> Echo off for line so don't try and send any text back
If you removed the
\x10
from the string in what you wrote, you would see data back, but you'd also see some extra characters (like the code you write echoed back to you, plus a newline and=
and then your answer)It's much easier to just stop Espruino writing stuff automatically with
\x10
and then to explicitly tell it to write stuff withBluetooth.println
-
• #25
i really appreciate your help...
i have reverted to the hub and mqtt. and can send commands, but how am i able to receive a function response from the puck.Many thanks
How am i able to send a command from the Raspberry pi to the Puck.js without having to install the hub scripts.
i.e. connect over bluetooth to the puck.js send command and disconnect or some other nifty efficient way. i would like to send command from rpi to puck.js to send IR signal
Thanks