Using Noble to communicate with BLE device - node.js

I have spent the last couple of days researching and understanding GATT to control my new adjustable bed which I can currently only control via Manufacturer's app but I want to control via my smart home setup.
I am able to get characteristics which are read and write with/without response so I know I am on right track and I have used PacketLogger on OSX to get values which I now know are acceptable when sent by myself using an IOS app called BLE Scanner which just asks for a Hex or Text Value to send to the characteristics for the device (bed) and I have sent the values I extracted from PacketLogger when using the manufacturer's app (5212 006E 0100 4EBD) as Hex separately and it vibrates the bed!
I just need to be able to this myself now with Noble by sending either straight to the peripheral.writeHandle function or via the characteristic.write function. I have tried many different things but I don't get the same effect as BLE Scanner app when it sends the values individually as Hex so I know the device isn't happy with what i'm sending. I noticed there is some padding added for what I think is L2CAP but as I say BLE Scanner just works for (5212 006E 0100 4EBD) as long as they are sent separately as Hex.
Would really appreciate some help to get me over the line.
I have tried so far to write to the characteristic and also tried direct to the periphel as there is no mention of the characteristic UUID in the PacketLogger logs when writing via BLE Scanner whereas when using the Manaufacturer app PacketLogger shows the write characteristic UUID so both I think will work.
I have tried many variations of
peripheral.writeHandle(18, Buffer.from("5212006E01004EBD", "hex"),
true, function(err) { console.log('writehandle'+err) });
and
characteristic.write(Buffer.from("5212006E01004EBD", "hex"), true,
function (error) {
if (!error) {
console.log("write succesful");
} else {
console.log("write unsuccesful");
}
}.bind(this));
I do see a difference in the ATT Send PacketLogger entry for the BLE Scanner App which works and my attempt in Noble which doesn't work - Write Request - Handle:0x0012 - Value: 5212 006E 0100 4EBD Opcode is 0x0012 is the working packetlogger entry for BLE Scanner whereas my attempt shows multiple entries for each attempt and the first entry is always Exchange MTU Request - MTU: 104 and the Opcode is 0x0002. No matter what I change in Noble the Opcode remains the same.

Related

Johnny-Five, I2C, Controlling multiple temperature sensors using ESP8266

I'm trying figure out how to control multiple temperature sensors.
THE SETUP:
2 ESP8266 Micro Controllers
2 MCP9808 Temperature Sensors
1 Machine controlling both ESPs using Johnny-Five.
NOTE: Each ESP8266 micro controller handles one MCP9808 Temperature Sensor.
THE GOAL:
The central machine (MacOS running Johnny-Five) handles both microcontrollers under one Node JS script.
THE PROBLEM:
I can control one Micro Controller / Temperature pairing, but not both under the same script.
Apparently the key to handling both at once lies in knowing how to handle the IC2 addressing.
So far I haven't been able to find any pages, forums, instructions or combinations thereof that clearly explain the logic in terms that I can understand.
THE QUESTION:
How to handle I2C using Johnny-Five to control multiple devices
THE CODE:
It only works when handling one Sensor, not both
In other words with the 4th line commented out it works. Uncommented, it doesn't.
var five = require("johnny-five");
var {EtherPortClient}=require("etherport-client");
var Thermometers=[
//{Name:"Thermometer1", Ip:"192.168.1.101"}, //Uncommenting causes fail.
{Name:"Thermometer2", Ip:"192.168.1.102"}
];
TrackThermometers();
function TrackThermometers(){
Thermometers.forEach(function(ThisThermometer, ThermometerCount){
ThisThermometer.Board=new five.Board({
port: new EtherPortClient({
host: ThisThermometer.Ip,
port: 3030
}),
repl: false
});
ThisThermometer.Board.on("ready", function(){
ThisThermometer.Controller=new five.Thermometer({ //This cmd triggers the error
controller:"MCP9808"
});
ThisThermometer.Controller.on("change", function(){
console.log(this.id, this.fahrenheit);
});
})
});
}
SOLUTION
There is a board property (undocumented as of this post) under the J5's Thermometer API. Assigning the Board instance in question to that property associates the Thermometer instance with that board.
By way of example the above code would be edited as follows...
ThisThermometer.Controller=new five.Thermometer({
board: ThisThermometer.Board, //<-- the missing magic
controller:"MCP9808"
});
Thanks to Donovan Buck for figuring this out. May be documented soon.

WebUSB and FTDI232

I try to connect to a serial-usb interface (FT232) but can't find anything on how to configure it...
What I've got :
A serial to USB interface from FTDI, it's a TTL-232RG-VSW5V-WE from this page
A custom board sending messages through RS232
What I need :
I need to connect to this interface using WebUSB, send messages, read messages.
What I've achieved :
Right now, I can connect to the interface and "read" something.
My problem :
I can't find anything on the web on how to configure the USB interface, the serial port configuration must be 57600 baud/s, E, 8, 1 but nothing I could find told how to configure these values...
See the following code, from what I understood, I've got to put some value in the controlTransferOut but I can't find what to put and why..
device = await navigator.usb.requestDevice({ 'filters': [] });
console.log(device);
await device.open();
if (device.configuration === null) {
await device.selectConfiguration(1);
}
await device.claimInterface(0);
await device.selectAlternateInterface(0, 0);
await device.controlTransferOut({ /* WHAT DO I PUT HERE?? */ });
let result = await device.transferIn(1, 64);
console.log((new TextDecoder).decode(result.data));
What I can read from the "What I've achieved" section is single chars because the serial is not well configured.
I tweaked it though to kindda make it work, I've opened the serial port with another software, configured it, closed the other software, then connect to the USB interface with webusb and read messages. That worked, but way to complicated...
Any help would be REALLY appreciated :)
According to the datasheet your TTL-232RG-VSW5V-WE cable contains a FT232R chip. The datasheet for that is here. I was hoping to discover a description of the protocol that the chip supports but all I found was documentation for their proprietary drivers.
On the other hand I know that Linux supports these chips so there must be code in the kernel driver for setting baud rate. The function in question is change_speed() in ftdi_sio.c.
From this it appears that the control transfer you need to send is,
device.controlTransferOut({ requestType: 'vendor',
recipient: 'device',
request: 3 /* FTDI_SIO_SET_BAUDRATE_REQUEST */,
value: divisor_value,
index: divisor_index });
divisor_value and divisor_index are the lower and upper 16 bits of the chip's clock divisor which is calculated by the ftdi_232bm_baud_to_divisor function based on the baud rate requested.
Hopefully this is a good start towards reading the code and figuring out what you need.
Thank you, very much. It works like a charm.
I figured out for baud rate 9600:
device.controlTransferOut({
requestType: "vendor",
recipient: "device",
request: 3 /* FTDI_SIO_SET_BAUDRATE_REQUEST */,
value: 16696, // divisor_value
index: 48000000 // divisor_index
});

Arduino - How to read a string from the Serial Port

I just recently started working with Arduino. I just have a quick question, I tried searching for an answer but have failed for days. Basically what I wanna ask is if there is a way to read a whole line from the Serial Port. Like the line highlighted in the picture below.
What I'm trying to do is using a Bluesmirf Silver Rn-42 to search the area for a bluetooth device and trigger a signal if a matching address is found. I just cant figure out how to read messages that are already on the Serial port.
Use .readString()
Example code:
String myString;
void setup()
{
Serial.begin(9600);
}
void loop()
{
while (Serial.available())
{
myString = Serial.readString();
//do stuff with the string
}
}
If you want to read something that's already in the serial port from the Arduino end, then you need to rethink your code. Anything you produce within your code to print to the serial monitor will already be in your program ready to access if you make it available in the right way. The exemplar string you provided, is simply an array of characters that you can store in an element within an array, making it accessible whenever you need it.
Hints:
Never read back from the serial monitor, it's really slow -.-
Make all the resources you require accessible and available in memory at the time you need it to save hassel & processing power.
Never make the same mistake twice.
However, if you want to read from the COM port that the Arduino is connected to in Windows, then you'll need to work with Libusb libraries found here: http://www.libusb.org/ for C. Any other language will be library or import dependent.

How can I connect a EV3 mindstorms via bluotooth to a unity game using unityscript?

I am making a race game in Unity with Unityscript and I made a steer with the lego mindstorms EV3 robot. I let te robot send information by bluetooth to the game, but I can't find how I can do that.
I already have the code for the bluetooth running and working a C#, but know I need to know how to translate it to unityscript.
I already tried to find it on google, but I only seem to get some software to hack the robot, but not to make code in unityscript for connecting the steer.
Under here stands the C# code:
// EV3: The EV3Messenger is used to communicate with the Lego EV3.
private EV3Messenger ev3Messenger;
// EV3: Create an EV3Messenger object which you can use to talk to the EV3.
ev3Messenger = new EV3Messenger();
// EV3: Connect to the EV3 serial port over Bluetooth.
// If the program 'hangs' on a call to ev3Messenger.Connect,
// then your EV3 is not paired with your PC yet/anymore.
// To pair: Remove the EV3 from the Windows Bluetooth device list and add it again.
ev3Messenger.Connect("COM3"); // Hardcoded serial port: put the serial port
// of the Bluetooth connection to your EV3 here!
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// all content.
/// </summary>
protected override void UnloadContent()
{
// Unload any non ContentManager content here
// EV3: Disconnect
if (ev3Messenger.IsConnected)
{
ev3Messenger.Disconnect();
}
}
// EV3: send Brake message to mailbox with name "MakeNoise"
if (ev3Messenger.IsConnected)
{
ev3Messenger.SendMessage("MakeNoise", "Brake");
}
// Game can be controlled by both the arrow keys and the Steer, gas and brake paddle of the connected EV3
UpdatePaddlePositionUsingKeys();
UpdatePaddlePositionUsingEV3();
base.Update(gameTime);
}
///Steer update
private void UpdatePaddlePositionUsingEV3()
{
if (ev3Messenger.IsConnected)
{
// EV3: Receive a new command from mailbox "COMMAND" of the EV3
// and use it to change the direction of the paddle or to exit the game.
EV3Message message = ev3Messenger.ReadMessage();
if (message != null
&& message.MailboxTitle == "Command")
{
if (message.ValueAsText == "")
{
}
{
ev3Messenger.Disconnect();
Exit();
}
}
}
}
I hope that you know where I can find how I can do this or even help me further.
If you want the original code for a small pong game where I got my inspiration from, just comment it.
I hope you can help me.
Here are some useful links with documentation on the EV3 firmware :
Firmware Documentation
LMS2012 Documentation
HDK/SDK
In particular, you need to learn how to send direct commands and then use that to read and write bluetooth mailboxes.
For communicating with the COM port itself using javascript, just do a little searching. For example, I found this SO question which has quite a few different ideas.
As part of c4ev3, We open-sourced our EV3 uploader, which can also be used to send connection-agnostic commands to the device.
Here is how you would move the motors in Perl (Complete version):
use IPC::Open2;
print open2(\*EV3OUT, \*EV3IN, "ev3 tunnel") or die "couldn't find: %!";
print EV3IN "0900xxxx8000 00 A3 00 09 00\n";
print EV3IN "0C00xxxx8000 00 A4 00 09 50 A6 00 09\n";
This would probe for an EV3 accessible over USB, Bluetooth or WiFi and connect to it, then send the direct messages associated with turning the motors. For more information on the direct commands protocol check out LEGO's Communication Developer Manual and David Lechner's answer.
Alternatively, you can write a C program for the EV3 with c4ev3 and communicate with that. That way you got a nicer looking C-API you can use.

Connect to LightBlue peripheral mode

I used LightBlue app on an IOS Devices (iPhone 4s, iOS 6.1.3) in peripheral mode and another IOS device (iPhone 4s, iOS 6.1.3) in a central mode.
I'm using BTLE Transfer example code from Apple, it's working properly on these two devices. However, It does not work on LightBlue. As I just want to develop a simple app that read data from Blood Pressure Device, I've just changed the following service and characteristic UUID in Transfer.h file
define TRANSFER_SERVICE_UUID #"1810"
define TRANSFER_CHARACTERISTIC_UUID #"2A49" // just read value
My plan is going to clone a real device structure on LightBlue and then develop a central app to connect with LightBlue peripheral (I think it then will work with real devices because I donot have any real device at the moment). I set a device as a peripheral and the second one will install modified app (from apple sample) as a central or client.
The following delegate method provided by Apple:
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
// Reject any where the value is above reasonable range
if (RSSI.integerValue > -15) {
return;
}
// Reject if the signal strength is too low to be close enough (Close is around -22dB)
if (RSSI.integerValue < -35) {
return;
}
NSLog(#"Discovered %# at %#", peripheral.name, RSSI);
// Ok, it's in range - have we already seen it?
if (self.discoveredPeripheral != peripheral) {
// Save a local copy of the peripheral, so CoreBluetooth doesn't get rid of it
self.discoveredPeripheral = peripheral;
// And connect
NSLog(#"Connecting to peripheral %#", peripheral);
[self.centralManager connectPeripheral:peripheral options:nil];
self.connectingPeripheral=peripheral; // this line of code I have added as recommended from a member
}
}
And the problem is, this delegate method have been fired and log panel display "Discovered LightBlue at -32".It likely cannot connect to the Lightblue peripheral as I cannot see the output of the line of code NSLog(#"Connecting to peripheral %#", peripheral);
All suggestion are welcome and highly appreciated.

Resources