Am trying to establish automated serial connection with a medical bluetooth device.
For ex .
the device is paired with a comport number 20 .The problem in this device is once the device is turned off ,it disconnects the bluetooth connection resulting the comport in some inaccessible state.(ie. when i try to open the create file handle returns 0x79 -ERROR_SEM_TIMEOUT).
So i tried polling for the comport connection as shown below in main thread ,
{
......
do
{
hSerial = CreateFileA(pcomport,
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
IO_ATTRIBUTE,
0);
if (hSerial == INVALID_HANDLE_VALUE)
{
result = GetLastError();
if (ERROR_FILE_NOT_FOUND == result)
{
//serial port does not exist. Inform user and exit for now...
printf("spc [OpenSerialPort]:unable to detect COM port: %s\n", pcomport);
return hSerial;
}
//some other error occurred. Inform user.
printf("spc [OpenSerialPort]:unknown error 0x%08x at %s\n", result, pcomport);
CloseHandle(hSerial);
//return hSerial;
}
} while (hSerial == INVALID_HANDLE_VALUE);
....
}
This seems to work fine .But the problem am facing is when i try to open some other device comport where bluetooth connection is maintained ,it fails .(may be because of polling with a win api ).
I couldnt find any method in msdn to detect the connection is established.
How can i automate this scenario .ie ,whenever the device is on ,the serial port should be opened and should continue in next cycle.
Related
I am able to connect a Raspberry Pi 4 an and Arduino Nano BLE through bluepy for Rpi4 and ArduinoBLE.h for Arduino Nano BLE. Unfortunately when I try to write from Rpi4 to Arduino Nano BLE, I'm not seeing the expected output for Read and Write. I don't see any perfect example for Arduino Nano BLE since it is recently released hardware with built-in BLE. It would be very helpful if anyone could help me achieve communication between them. Thanks in advance. Below is my code for Raspberry Pi.
import bluepy.btle as btle
p = btle.Peripheral("de:fc:54:87:b0:04")
services=p.getServices()
s = p.getServiceByUUID(list(services)[2].uuid)
c = s.getCharacteristics()[0]
c.write(bytes("2", "utf-8"))
p.disconnect()
And I'm using the Arduino built-in example from the Arduino Nano BLE Library.
#include <ArduinoBLE.h>
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
const int ledPin = LED_BUILTIN; // pin to use for the LED
void setup() {
Serial.begin(9600);
while (!Serial);
// set LED pin to output mode
pinMode(ledPin, OUTPUT);
// begin initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
// set advertised local name and service UUID:
BLE.setLocalName("LED");
BLE.setAdvertisedService(ledService);
// add the characteristic to the service
ledService.addCharacteristic(switchCharacteristic);
// add service
BLE.addService(ledService);
// set the initial value for the characeristic:
switchCharacteristic.writeValue(0);
// start advertising
BLE.advertise();
Serial.println("BLE LED Peripheral");
}
void loop() {
// listen for BLE peripherals to connect:
BLEDevice central = BLE.central();
// if a central is connected to peripheral:
if (central) {
Serial.print("Connected to central: ");
//prints the centrals MAC address:
Serial.println(central.address());
// while the central is still connected to peripheral:
while (central.connected()) {
// if the remote device wrote to the characteristic,
// use the value to control the LED:
if (switchCharacteristic.written()) {
if (switchCharacteristic.value()) { // any value other than 0
Serial.println("LED on");
digitalWrite(ledPin, HIGH); // will turn the LED on
} else { // a 0 value
Serial.println(F("LED off"));
digitalWrite(ledPin, LOW); // will turn the LED off
}
}
}
// when the central disconnects, print it out:
Serial.print(F("Disconnected from central: "));
Serial.println(central.address());
}
}
I figured out myself, it was the value in the write which was going wrong all this time. Below is the right one. I hope now you can find this as a perfect solution to connect raspberry Pi 4 and Arduino Nano BLE wirelessly Via Bluetooth.
c.write(bytes("0001".encode())
I completed this tutorial and can see data sent to Azure's cloud.
https://microsoft.github.io/azure-iot-developer-kit/docs/get-started/
But, looking at the serial monitor, I see it disconnecting and reconnecting over and over, between the successful sensor messages.
[...] hardware\stm32f4\1.6.0\cores\arduino\azure-iot-sdk-c\c-utility\adapters\socketio_mbed_os5.c Func:send_queued_data Line:213,
Socketio_Failure: encountered unknow connection issue, the connection will be restarted.
2019-03-27 00:35:28 INFO: >>>Connection status: disconnected
2019-03-27 00:35:30 INFO: >>>Re-connect.
My connection seems fine, judging by Google's speed test.
It's connection issue, the IoT DevKit only support 2.4GHz Wi-Fi, please make sure not connect with a 5GHz AP.
If 2.4GHz, can you try another AP? Like set your cell phone as a Hotspot.
Wasn't able to run the Get Started project on any connection, but I just created a new IotHub Project from scratch in Studio Code and it now stays connected.
Maybe I needed to update my firmware or something, I'll try it later, but if someone has the same issue and wants to get running, here's the simple working code that was generated:
#include "AZ3166WiFi.h"
#include "DevKitMQTTClient.h"
static bool hasWifi = false;
static bool hasIoTHub = false;
void setup() {
// put your setup code here, to run once:
if (WiFi.begin() == WL_CONNECTED)
{
hasWifi = true;
Screen.print(1, "Running...");
if (!DevKitMQTTClient_Init())
{
hasIoTHub = false;
return;
}
hasIoTHub = true;
}
else
{
hasWifi = false;
Screen.print(1, "No Wi-Fi");
}
}
void loop() {
// put your main code here, to run repeatedly:
if (hasIoTHub && hasWifi)
{
char buff[128];
// replace the following line with your data sent to Azure IoTHub
snprintf(buff, 128, "{\"topic\":\"iot\"}");
if (DevKitMQTTClient_SendEvent(buff))
{
Screen.print(1, "Sending...");
}
else
{
Screen.print(1, "Failure...");
}
delay(2000);
}
}
I have a server to collect Tcp data from different clients to a certain port. I have a scenario that whenever the client creates tcp connection and remain idle for more than let's say 30 min then I need to close the connection.
I have learned about TCP keep alive to track that the peer is dead or not and Mostly I found examples used in client side. Similarly can I used in the server side to poll the connection whether it is active or not?
Further In linux sysctl.conf , there is a configuration file to edit the values. This seems that the whole tcp connection is destroyed after certain inactivity. I am in need such that certain connection form the device are destroyed after certain time inactivity but not the whole tcp port connection closed.
I am using ubuntu to create the server to collect tcp connection. Can I use TCP Keep-Alives in server code to find the inactive client and close the particular client? or is there any other way in server side to implement such feature?
and while going through the web it is mentioned that
(getsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen)
this getsockopt is for the main tcp connection and setting here seems the setting is for whole connection to the server.
However what I need is for the specific client. I have the event server code as
here client_fd is accepted and now I need to close this client_fd if next data through this client is not received within certain time.
void event_server(EV_P_ struct ev_io *w, int revents) {
int flags;
struct sockaddr_in6 addr;
socklen_t len = sizeof(addr);
int client_fd;
// since ev_io is the first member,
// watcher `w` has the address of the
// start of the _sock_ev_serv struct
struct _sock_ev_serv* server = (struct _sock_ev_serv*) w;
server->socket_len = len;
for (;;) {
if ((client_fd = accept(server->fd, (struct sockaddr*) &addr, &len)) < 0) {
switch (errno) {
case EINTR:
case EAGAIN:
break;
default:
zlog_info(_c, "Error accepting connection from client \n");
//perror("accept");
}
break;
}
char ip[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &addr.sin6_addr, ip, INET6_ADDRSTRLEN);
char *dev_ip = get_ip(ip);
server->device_ip = dev_ip;
zlog_debug(_c,"The obtained ip is %s and dev_ip is %s", ip, dev_ip);
/** check for the cidr address for config_ip **/
char *config_ip;
config_ip = get_config_ip(dev_ip, _client_map);
zlog_debug(_c,"The _config ip for dev_ip:%s is :%s", dev_ip, config_ip);
if (config_ip == NULL) {
zlog_debug(_c,"Connection attempted from unreigistered IP: %s", dev_ip);
zlog_info(_c, "Connection attempted from unregistered IP : %s", dev_ip);
AFREE(server->device_ip);
continue;
}
json_t *dev_config;
dev_config = get_json_object_from_json(_client_map, config_ip);
if (dev_config==NULL) {
zlog_debug(_c,"Connection attempted from unreigistered IP: %s", dev_ip);
zlog_info(_c, "Connection attempted from unregistered IP : %s", dev_ip);
AFREE(server->device_ip);
continue;
}
if ((flags = fcntl(client_fd, F_GETFL, 0)) < 0 || fcntl(client_fd, F_SETFL, flags | O_NONBLOCK) < 0) {
zlog_error(_c, "fcntl(2)");
}
struct _sock_ev_client* client = malloc(sizeof(struct _sock_ev_client));
client->device_ip = dev_ip;
client->server = server;
client->fd = client_fd;
// ev_io *watcher = (ev_io*)calloc(1, sizeof(ev_io));
ev_io_init(&client->io, event_client, client_fd, EV_READ);
ev_io_start(EV_DEFAULT, &client->io);
}
}
TCP keep alives are not to detect idle clients but to detect dead connections, i.e. if a client crashed without closing the connection or if the line is dead etc. But if the client is only idle but not dead the connection is still open. Any attempts to send an empty packet (which keep-alive packets are) to the client will result in an ACK from the client and thus keep alive will not report a dead connection.
To detect idle clients instead use either timeouts for read (SO_RCVTIMEO) or use a timeout with select, poll or similar functions.
I have implemented below mechanism to detect idle status on Socket IO activity.
My Socket is wrapped in some class like UserConnection. This class has one more attribute lastActivtyTime. Whenever I get a read on write on this Socket, I will update this attribute.
I have one more background Reaper thread, which will iterate through all UserConnection objects and check for lastActivtyTime. If current time - lastActivtyTime is greater than configured threshold parameter like 15 seconds, I will close the idle connection.
In your case, when you are iterating through all UserConnections, you can check client_id and your threshold of 30 minutes inactivity to close idle connection.
Here's my problem. I have an Arduino Mega 2560 connected with USB on my pc (windows 7).On the arduino i have connected a bluetooth device HC-06. I upload the following the program to my arduino:
#include <SoftwareSerial.h>// import the serial library
SoftwareSerial Genotronex(14, 15); // RX, TX
int BluetoothData; // the data given from Computer
void setup() {
// put your setup code here, to run once:
Genotronex.begin(9600);
}
void loop() {
BluetoothData=Genotronex.read(); //read incoming data
Genotronex.println(BluetoothData); //print data received from bluetooth
delay(100);// prepare for next data ...
}
I successfully connect my arduino with the bluetooth. Next i use putty and connect to the bluetooth but the problem is that it prints "-1" meaning that the incoming data to the bluetooth is "-1" although i do not send any data from any other progamm. I also tried to send other data from putty but it didn't work. Thanks and sorry for my english.
Try something like that to be sure that you received some data before send them to computer
void loop()
{
if (Genotronex.available())
{
BluetoothData=Genotronex.read();
Genotronex.write(BluetoothData);
}
delay(100);
}
And Have you check the HC-06 configuration ?
Here
and Here
A battery powered (2 x AA) Arduino LilyPad should switch a BlueSmirf v2.11 Bluetooth modem to/from command mode (see source code below). The BlueSmirf has been set to 9600 baud.
If the PC connects via Bluetooth (see source code below), the Arduino program runs fine at the beginning (sending multiple "ping\n"). After some time it (LilyPad/BlueSmirf) starts to also send "$$$" and "---\n" over the Bluetooth connection instead of switching to/from command mode.
Any ideas?
Regards,
tamberg
// Arduino source code:
void setup () {
Serial.begin(9600);
}
void loop () {
Serial.print("$$$");
delay(2000); // TODO: Inquiry, etc.
Serial.print("---\n");
delay(100);
Serial.print("ping\n");
delay(2000);
}
// C# source code (runs on PC)
using System;
using System.IO.Ports;
class Program {
static void Main () {
SerialPort p = new SerialPort(
"COM20", 9600, Parity.None, 8, StopBits.One);
using (p) {
p.Open();
while (p.IsOpen) {
Console.Write((char) p.ReadChar());
}
}
}
}
From the datasheet, page 6:
NOTE1 : You can enter command mode
locally over the serial port at any
time when not connected. Once a
connection is made, you can only enter
command mode if the config timer has
not expired. To enable continuous
configuration, set the config timer to
255. Also, if the device is in Auto Master mode 3, you will NOT be able to
enter command mode when connected over
Bluetooth.
My guess would be that the config timer is expiring.