ESP8266 WIFI Connection lost after Acces Point reboot - ide

Heyho,
at first, I am no programmer - it's just my hobby :)
I have a cistern in my garden and I want to measure the level of it with an ESP8266 and an ultrasonic sensor.
I am sending the data via mqtt to my mqtt broker.
Everything working well but when my accesspoint is rebooting two times a day and after that reboot the ESP8266 doesn't connect to the WIFI again.
What I've done so far:
setting the WiFi.setAutoReconnect(true); to true (find that in the Internet)
call the function setup(); in void loop() again
So, I think I have a mistake in thinking with that problem.
Heres my code:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Ultrasonic.h>
Ultrasonic ultrasonic(12, 13);
const char* ssid = "XXX"; // Enter your WiFi name
const char* password = "XXX"; // Enter WiFi password
const char* mqttServer = "XXX";
const int mqttPort = 1883;
const char* mqttUser = "XXX";
const char* mqttPassword = "XXX";
#define abstand_topic "home/zisterne/fuellstand"
#define abstand_topic_2 "home/zisterne/mittl_fuellstand"
const int RunningAverageCount = 24; // Anzahl der in den Laufenden-Mettelwert aufgenommenen Messungen
float RunningAverageBuffer[RunningAverageCount];
int NextRunningAverage;
unsigned long previousMillis = 0;
unsigned long interval = 30000;
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
WiFi.setAutoReconnect(true);
WiFi.persistent(true);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connected to the WiFi network");
client.setServer(mqttServer, mqttPort);
client.setCallback(callback);
while (!client.connected()) {
Serial.println("Connecting to MQTT...");
if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
Serial.println("connected");
} else {
Serial.print("failed with state ");
Serial.print(client.state());
delay(2000);
}
}
// //Sensor auslesen und übergeben
// int Sensor = ultrasonic.distanceRead();
// char Abstand[10];
// itoa(Sensor,Abstand,10);
//
// Serial.println(ultrasonic.distanceRead());
// client.publish(abstand_topic, Abstand);
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived in topic: ");
Serial.println(topic);
Serial.print("Message:");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
Serial.println("-----------------------");
}
void loop() {
client.loop();
//WLAN Reconnect
if (WiFi.status() != WL_CONNECTED) {
delay(500);
setup();
}
//Sensor auslesen und übergeben
int Sensor = ultrasonic.distanceRead();
char Abstand[10];
itoa(Sensor,Abstand,10);
Serial.println(ultrasonic.distanceRead());
client.publish(abstand_topic, Abstand);
//unsigned long minutes = 1000 * 300;
float RawDistance = ultrasonic.distanceRead();
RunningAverageBuffer[NextRunningAverage++] = RawDistance;
if (NextRunningAverage >= RunningAverageCount)
{
NextRunningAverage = 0;
}
float RunningAverageDistance = 0;
for(int i=0; i< RunningAverageCount; ++i)
{
RunningAverageDistance += RunningAverageBuffer[i];
}
RunningAverageDistance /= RunningAverageCount;
int mittelwert = RunningAverageDistance;
char mittl_Abstand[10];
itoa(mittelwert,mittl_Abstand,10);
client.publish(abstand_topic_2, mittl_Abstand);
delay(5000);
yield();
}
So, now I hope someone of you can help me with my small problem! :)
Greetings,
Philipp

Related

Error in uploading sensor data to Azure IOT central

I have watched this video and tried to implement the same using all the required components and I have been getting errors in getting connected to the portal and am neither getting output from sensors.
this is the code that I have been using:
`
#include "DHT.h" // including the library of DHT11 temperature and humidity sensor
#include <ESP8266WiFi.h>
#define DHTTYPE DHT11
#include "D:/ARDUINO/ESP8266/ESP8266/src/iotc/common/string_buffer.h"
#include "D:/ARDUINO/ESP8266/ESP8266/src/iotc/iot"
#include "D:/ARDUINO/ESP8266/ESP8266/src/connection.h"
#define dht_dpin 12 // creating the object sensor on pin 'D12'
DHT dht(dht_dpin, DHTTYPE);
#define WIFI_SSID "<ENTER WIFI SSID>"
#define WIFI_PASSWORD "<ENTER WIFI PASSWORD>"
const char* SCOPE_ID = "<ENTER SCOPE ID>";
const char* DEVICE_ID = "<ENTER DEVICE ID>";
const char* DEVICE_KEY = "<ENTER DEVICE KEY>";
int echoPin = D6;
int trigPin = D8;
int pingTravelTime;
float pingTravelDistance;
float distanceToTarget;
float speedOfsound;
void on_event(IOTContext ctx, IOTCallbackInfo* callbackInfo);
void on_event(IOTContext ctx, IOTCallbackInfo* callbackInfo) {
// ConnectionStatus
if (strcmp(callbackInfo->eventName, "ConnectionStatus") == 0) {
LOG_VERBOSE("Is connected ? %s (%d)",
callbackInfo->statusCode == IOTC_CONNECTION_OK ? "YES" : "NO",
callbackInfo->statusCode);
isConnected = callbackInfo->statusCode == IOTC_CONNECTION_OK;
return;
}
// payload buffer doesn't have a null ending.
// add null ending in another buffer before print
AzureIOT::StringBuffer buffer;
if (callbackInfo->payloadLength > 0) {
buffer.initialize(callbackInfo->payload, callbackInfo->payloadLength);
}
LOG_VERBOSE("- [%s] event was received. Payload => %s\n",
callbackInfo->eventName, buffer.getLength() ? *buffer : "EMPTY");
if (strcmp(callbackInfo->eventName, "Command") == 0) {
LOG_VERBOSE("- Command name was => %s\r\n", callbackInfo->tag);
}
dht.begin();
}
void setup() {
Serial.begin(9600);
connect_wifi(WIFI_SSID, WIFI_PASSWORD);
connect_client(SCOPE_ID, DEVICE_ID, DEVICE_KEY);
if (context != NULL) {
lastTick = 0; // set timer in the past to enable first telemetry a.s.a.p
}
pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);
}
void loop() {
digitalWrite(trigPin,LOW);
delayMicroseconds(10);
digitalWrite(trigPin,HIGH);
delayMicroseconds(10);
digitalWrite(trigPin,LOW);
float h = dht.readHumidity();
float t = dht.readTemperature();
// Reading the temperature in Celsius degrees and store in the t variable
// Reading the humidity index and store in the h variable
pingTravelTime = pulseIn(echoPin,HIGH);
delay(25);
pingTravelDistance = (pingTravelTime*330*100)/(1000000);
speedOfsound = (pingTravelDistance*1000000)/pingTravelTime;
distanceToTarget = pingTravelDistance/2;
if (isConnected) {
unsigned long ms = millis();
if (ms - lastTick > 10000) { // send telemetry every 10 seconds
char msg[64] = {0};
int pos = 0, errorCode = 0;
lastTick = ms;
if (loopId++ % 4 == 0) { // send telemetry
pos = snprintf(msg, sizeof(msg) - 1, "{\"Temperature\": %f}",
t);
errorCode = iotc_send_telemetry(context, msg, pos);
pos = snprintf(msg, sizeof(msg) - 1, "{\"Humidity\":%f}",
h);
errorCode = iotc_send_telemetry(context, msg, pos);
pos = snprintf(msg, sizeof(msg) - 1, "{\"Distance\":%f}",
distanceToTarget);
errorCode = iotc_send_telemetry(context, msg, pos);
pos = snprintf(msg, sizeof(msg) - 1, "{\"Speed\":%f}",
speedOfsound);
errorCode = iotc_send_telemetry(context, msg, pos);
} else { // send property
}
msg[pos] = 0;
if (errorCode != 0) {
LOG_ERROR("Sending message has failed with error code %d", errorCode);
}
}
iotc_do_work(context); // do background work for iotc
} else {
iotc_free_context(context);
context = NULL;
connect_client(SCOPE_ID, DEVICE_ID, DEVICE_KEY);
}
delay(50);
}
`
I tried to implement this project for a thesis of mine and was not getting the results since the connection is not being established.
These are the errors i was getting:
ERROR: couldn't fetch the time from NTP. - -
X - Error at connection.h:32
Error # tcp_connect. Code 1 -
ERROR: Client was not connected. - -
iot.dps : getting auth... -
iotc.dps : getting operation id... -
ERROR: DPS endpoint PUT call has failed.
this is the github link for downloading the required header files for connection establishment
I could reproduce the same error in my NodeMCU. Please find the below image for reference.
If you let the code run and observe the NodeMCU serial monitor, it will occasionally spit out additional information as you can find in the below image
The error message in my case indicates that it is an issue with Authorization. I had the wrong Primary key provided in the code. In order to be able to connect to the device on Azure IoT Central, make sure the device is not set to be simulated when you create it.
Once you have the device created from the template, navigate to the device and click on connect to get the following details that needs to be entered in the code. Attached the below image for reference.
Here is the code snippet I have used to generate data
#include <ESP8266WiFi.h>
#include "src/iotc/common/string_buffer.h"
#include "src/iotc/iotc.h"
#include "DHT.h"
#define DHTPIN 2
#define DHTTYPE DHT11 // DHT 11
#define WIFI_SSID "<SSID>"
#define WIFI_PASSWORD "<WIFIPASSWORD>"
const char *SCOPE_ID = "<value 2 from above image>";
const char *DEVICE_ID = "<value 3 from above image>";
const char *DEVICE_KEY = "<value 4 from above image>";
DHT dht(DHTPIN, DHTTYPE);
void on_event(IOTContext ctx, IOTCallbackInfo *callbackInfo);
#include "src/connection.h"
void on_event(IOTContext ctx, IOTCallbackInfo *callbackInfo)
{
// ConnectionStatus
if (strcmp(callbackInfo->eventName, "ConnectionStatus") == 0)
{
LOG_VERBOSE("Is connected ? %s (%d)",
callbackInfo->statusCode == IOTC_CONNECTION_OK ? "YES" : "NO",
callbackInfo->statusCode);
isConnected = callbackInfo->statusCode == IOTC_CONNECTION_OK;
return;
}
// payload buffer doesn't have a null ending.
// add null ending in another buffer before print
AzureIOT::StringBuffer buffer;
if (callbackInfo->payloadLength > 0)
{
buffer.initialize(callbackInfo->payload, callbackInfo->payloadLength);
}
LOG_VERBOSE("- [%s] event was received. Payload => %s\n",
callbackInfo->eventName, buffer.getLength() ? *buffer : "EMPTY");
if (strcmp(callbackInfo->eventName, "Command") == 0)
{
LOG_VERBOSE("- Command name was => %s\r\n", callbackInfo->tag);
}
}
void setup()
{
Serial.begin(9600);
connect_wifi(WIFI_SSID, WIFI_PASSWORD);
connect_client(SCOPE_ID, DEVICE_ID, DEVICE_KEY);
if (context != NULL)
{
lastTick = 0; // set timer in the past to enable first telemetry a.s.a.p
}
dht.begin();
}
void loop()
{
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isConnected)
{
unsigned long ms = millis();
if (ms - lastTick > 10000)
{ // send telemetry every 10 seconds
char msg[64] = {0};
int pos = 0, errorCode = 0;
lastTick = ms;
if (loopId++ % 2 == 0)
{ // send telemetry
pos = snprintf(msg, sizeof(msg) - 1, "{\"Temperature\": %f}",
t);
errorCode = iotc_send_telemetry(context, msg, pos);
pos = snprintf(msg, sizeof(msg) - 1, "{\"Humidity\":%f}",
h);
errorCode = iotc_send_telemetry(context, msg, pos);
}
else
{ // send property
}
msg[pos] = 0;
if (errorCode != 0)
{
LOG_ERROR("Sending message has failed with error code %d", errorCode);
}
}
iotc_do_work(context); // do background work for iotc
}
else
{
iotc_free_context(context);
context = NULL;
connect_client(SCOPE_ID, DEVICE_ID, DEVICE_KEY);
}
}
Here are the Temperature and Humidity values generated from the code
The data generated the following graph on the Azure IoT Central.
Please note that I have used DHT11 sensor and connected to read it from the GPI0 2 (D4) pin on my NodeMCU board. I have used the Arduino IDE version 1.8.19 and ESP8266 board version 2.7.4

PubSubClient & ArduinoJSON - Arduino passing char to digitalWrite

I am not sure how to pass the values in the function in order to be used within the digitalWrite functions.
I'm getting the following error:
error: cannot convert 'String' to 'uint8_t' {aka unsigned char}' for argument '1' to 'void digitalWrite(uint8_t, uint8_t)'
pubsub callback
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("New message on [");
Serial.print(topic);
Serial.print("] ");
Serial.println("");
char s[length];
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
s[i]=payload[i];
}
StaticJsonBuffer<500> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(s);
if (!root.success()) {
Serial.println("parseObject() failed");
}
String relay = root["relay"]; // "relayOne"
int time = root["timestamp"]; // 1351824120
String trigger = root["trigger"]; // "ON"
// Feel free to add more if statements to control more GPIOs with MQTT
commander(relay, trigger);
}
commander function
void commander(String relay, String trigger) {
if(trigger == "ON"){
Serial.print("Turning ");
Serial.println(relay);
Serial.println(" on");
digitalWrite(relay, HIGH);
} else if(trigger == "OFF"){
Serial.println(relay);
digitalWrite(relayOne, LOW);
Serial.print("TRIGGERED!");
} else {
// turn all the LEDs off:
for (int pin = 0; pin < relayPinCount; pin++) {
digitalWrite(relayPins[pin], LOW);
}
}
Serial.println();
}
void commander(String relay, String trigger) {
uint8_t pinNo;
if ( relay == "relayOne" ) {
pinNo = RELAY_1_PIN;
} else
if ( relay == "anotherRelay" ) {
pinNo = OTHER_RELAY_PIN;
} else
if ( ... ) {
...
} else {
return;
}
if(trigger == "ON"){
Serial.print("Turning ");
Serial.println(relay);
Serial.println(" on");
digitalWrite(pinNo, HIGH);
} else if(trigger == "OFF"){
Serial.println(relay);
digitalWrite(pinNo, LOW);
Serial.print("TRIGGERED!");
} else {
// turn all the LEDs off:
for (int pin = 0; pin < relayPinCount; pin++) {
digitalWrite(relayPins[pin], LOW);
}
}
Serial.println();
}

ESP8266 Sniffing and sending Mac address

I'm trying to make my ESP8266 sniffing nearby devices, then posting them by with a HTTP request. With purpose is to record when my roommate and I are at home. Then in the future, trigger certain tasks like turning on/off the lights if we're home or not. I don't care at all about the packets content just the mac addresses.
So fare I've found this, script that prints out the mac adresses for nearby devices, created by kalanda: esp8266-sniffer.
Aswell as this HTTP posting script ESP8266 http get requests.
I've tried to combine those two and in the callback function make the ESP send the found data, but doesn't look like the ESP establish the wifi connection.
I tried using different WIFI modes: STATION_MODE, SOFTAP_MODE, STATIONAP_MODE. None of them worked for both sniffing and http request at the same time. I know that the STATIONAP_MODE do have some flaws. What I've found is that it has to switch both somehow, but unfortunately I'm not a ESP expert and don't know how this can be done.
Here is my code(srry for any rubbish coding on my side):
#include <ESP8266WiFi.h> // added this
#include <ESP8266HTTPClient.h> // added this
const char* ssid = "**********"; // Wifi SSID
const char* password = "**********"; // Wifi Password
String main_url = "http://*********.php?"; // Website url to post the information
String temp_url = ""; // Url with information
extern "C" {
#include <user_interface.h>
}
#define DATA_LENGTH 112
#define TYPE_MANAGEMENT 0x00
#define TYPE_CONTROL 0x01
#define TYPE_DATA 0x02
#define SUBTYPE_PROBE_REQUEST 0x04
struct RxControl {
signed rssi:8; // signal intensity of packet
unsigned rate:4;
unsigned is_group:1;
unsigned:1;
unsigned sig_mode:2; // 0:is 11n packet; 1:is not 11n packet;
unsigned legacy_length:12; // if not 11n packet, shows length of packet.
unsigned damatch0:1;
unsigned damatch1:1;
unsigned bssidmatch0:1;
unsigned bssidmatch1:1;
unsigned MCS:7; // if is 11n packet, shows the modulation and code used (range from 0 to 76)
unsigned CWB:1; // if is 11n packet, shows if is HT40 packet or not
unsigned HT_length:16;// if is 11n packet, shows length of packet.
unsigned Smoothing:1;
unsigned Not_Sounding:1;
unsigned:1;
unsigned Aggregation:1;
unsigned STBC:2;
unsigned FEC_CODING:1; // if is 11n packet, shows if is LDPC packet or not.
unsigned SGI:1;
unsigned rxend_state:8;
unsigned ampdu_cnt:8;
unsigned channel:4; //which channel this packet in.
unsigned:12;
};
struct SnifferPacket{
struct RxControl rx_ctrl;
uint8_t data[DATA_LENGTH];
uint16_t cnt;
uint16_t len;
};
static void showMetadata(SnifferPacket *snifferPacket) {
unsigned int frameControl = ((unsigned int)snifferPacket->data[1] << 8) + snifferPacket->data[0];
uint8_t version = (frameControl & 0b0000000000000011) >> 0;
uint8_t frameType = (frameControl & 0b0000000000001100) >> 2;
uint8_t frameSubType = (frameControl & 0b0000000011110000) >> 4;
uint8_t toDS = (frameControl & 0b0000000100000000) >> 8;
uint8_t fromDS = (frameControl & 0b0000001000000000) >> 9;
// Only look for probe request packets
if (frameType != TYPE_MANAGEMENT ||
frameSubType != SUBTYPE_PROBE_REQUEST)
return;
Serial.print("RSSI: ");
Serial.print(snifferPacket->rx_ctrl.rssi, DEC);
Serial.print(" Ch: ");
Serial.print(wifi_get_channel());
char addr[] = "00:00:00:00:00:00";
getMAC(addr, snifferPacket->data, 10);
Serial.print(" Peer MAC: ");
Serial.print(addr);
uint8_t SSID_length = snifferPacket->data[25];
Serial.print(" SSID: ");
printDataSpan(26, SSID_length, snifferPacket->data);
Serial.println();
if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
{
HTTPClient http; //Declare an object of class HTTPClient
temp_url = main_url;
temp_url = temp_url + "mac=30:a8:db:96:a4:75";
temp_url = temp_url + "&rssi=-90";
temp_url = temp_url + "&ssid=none";
http.begin(temp_url); //Specify request destination
int httpCode = http.GET(); //Send the request
temp_url = "";
if (httpCode > 0)
{ //Check the returning code
String payload = http.getString(); //Get the request response payload
Serial.println(payload); //Print the response payload
}
http.end(); //Close connection
}
else
{
Serial.println("Wifi connection failed"); //Prints out this
}
}
/**
* Callback for promiscuous mode
*/
static void ICACHE_FLASH_ATTR sniffer_callback(uint8_t *buffer, uint16_t length) {
struct SnifferPacket *snifferPacket = (struct SnifferPacket*) buffer;
showMetadata(snifferPacket);
}
static void printDataSpan(uint16_t start, uint16_t size, uint8_t* data) {
for(uint16_t i = start; i < DATA_LENGTH && i < start+size; i++) {
Serial.write(data[i]);
}
}
static void getMAC(char *addr, uint8_t* data, uint16_t offset) {
sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", data[offset+0], data[offset+1], data[offset+2], data[offset+3], data[offset+4], data[offset+5]);
}
#define CHANNEL_HOP_INTERVAL_MS 1000
static os_timer_t channelHop_timer;
/**
* Callback for channel hoping
*/
void channelHop()
{
// hoping channels 1-14
uint8 new_channel = wifi_get_channel() + 1;
if (new_channel > 14)
new_channel = 1;
wifi_set_channel(new_channel);
}
#define DISABLE 0
#define ENABLE 1
void setup() {
// set the WiFi chip to "promiscuous" mode aka monitor mode
Serial.begin(115200);
delay(10);
wifi_set_opmode(STATION_MODE);
wifi_set_channel(1);
wifi_promiscuous_enable(DISABLE);
delay(10);
wifi_set_promiscuous_rx_cb(sniffer_callback);
delay(10);
wifi_promiscuous_enable(ENABLE);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print("Connecting..");
}
Serial.println("");
Serial.println("Connected..");
// setup the channel hoping callback timer
os_timer_disarm(&channelHop_timer);
os_timer_setfn(&channelHop_timer, (os_timer_func_t *) channelHop, NULL);
os_timer_arm(&channelHop_timer, CHANNEL_HOP_INTERVAL_MS, 1);
}
void loop() {
delay(10);
}
Here's the code which aggregates probe requests (MAC addresses and RSSIs) for 3 seconds and then sends them to specified server's endpoint using json (WIFI_AP_STA mode):
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266HTTPClient.h>
#include <vector>
const char* apSsid = "ap-ssid";
const char* apPassword = "ap-password";
const char* clientSsid = "client-ssid";
const char* clientPassword = "client-password";
HTTPClient http;
WiFiEventHandler probeRequestPrintHandler;
String macToString(const unsigned char* mac) {
char buf[20];
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(buf);
}
std::vector<WiFiEventSoftAPModeProbeRequestReceived> myList;
void onProbeRequestPrint(const WiFiEventSoftAPModeProbeRequestReceived& evt) {
myList.push_back(evt);
}
void setup() {
Serial.begin(115200);
Serial.println("Hello!");
// Don't save WiFi configuration in flash - optional
WiFi.persistent(false);
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(apSsid, apPassword);
WiFi.begin(clientSsid, clientPassword);
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(100);
}
Serial.println("");
probeRequestPrintHandler = WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequestPrint);
}
void loop() {
delay(3000);
String json = "";
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
JsonArray& probes = root.createNestedArray("probes");
for(WiFiEventSoftAPModeProbeRequestReceived w : myList){
JsonObject& probe = probes.createNestedObject();
probe["address"] = macToString(w.mac);
probe["rssi"] = w.rssi;
}
myList.clear();
root.printTo(json);
Serial.println("json:" + json);
http.begin("http://example.com/api/v1/probe");
http.addHeader("Content-Type", "application/json");
http.POST(json);
http.end();
}
Remember to use the latest version (actually a pre-release - 2.4.0-rc1 or newer) of arduino-esp8266 library since those WiFiEvents were just recently added.
You can download ArduinoJson library using Library Manager (Sketch -> Include Library -> Manage Libraries...) if you don't have that already.

How to listen continuosly SSDP response after sending M-SEARCH

I would like to search Sat>IP servers on the network. Sat>IP servers advertise their presence to other Sat>IP servers and clients.
I must not continuosly send M-SEARCH messages but that instead it listens to server NOTIFY messages.
After initalizing network settings of my device, I'm sending M-SEARCH message and getting response if there is already any active Sat>IP server.
However, I couldn't get any response, If I opens Sat>IP server after sending M-SEARCH message.
Here's my code.
void SatIP::InitDiscoverThread()
{
if(INVALID_THREAD_CHK == DiscoverThreadChk)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
printf("InitDiscoverThread pthread_create\n");
DiscoverThreadChk = PTH_RET_CHK(pthread_create(&DiscoverThreadID, &attr, DiscoverThreadFunc, this));
if(DiscoverThreadChk != 0)
{
ASSERT(0);
}
}
}
void SatIP::FinalizeDiscoverThread()
{
if(INVALID_THREAD_CHK != DiscoverThreadChk)
{
printf("FinalizeDiscoverThread pthread_cancel\n");
pthread_cancel(DiscoverThreadID);
DiscoverThreadChk = INVALID_THREAD_CHK;
close(discoverSocket);
}
}
void *SatIP::DiscoverThreadFunc(void* arg)
{
SatIP* satip = (SatIP *)arg;
satip->ListenSSDPResponse();
pthread_exit(NULL);
}
bool SatIP::SendMSearchMessage()
{
vSatIPServers.clear();
FinalizeDiscoverThread();
const char *searchSatIPDevice = "M-SEARCH * HTTP/1.1\r\n" \
"HOST: 239.255.255.250:1900\r\n" \
"MAN: \"ssdp:discover\"\r\n" \
"MX: 2\r\n" \
"ST: urn:ses-com:device:SatIPServer:1\r\n\r\n";
struct sockaddr_in upnpControl, broadcast_addr;
discoverSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (discoverSocket == INVALID_SOCKET)
{
printf("socked failed INVALID_SOCKET\n");
return false;
}
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
if(setsockopt(discoverSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)) == SOCKET_ERROR)
{
printf("setsockopt timeout failed\n");
close(discoverSocket);
return false;
}
socklen_t ttl = 2;
if(setsockopt(discoverSocket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == SOCKET_ERROR)
{
printf("setsockopt TTL failed\n");
close(discoverSocket);
return false;
}
if(setsockopt(discoverSocket, SOL_SOCKET, SO_BROADCAST, searchSatIPDevice, sizeof(searchSatIPDevice)) == SOCKET_ERROR)
{
printf("setsockopt broadcast failed\n");
close(discoverSocket);
return false;
}
upnpControl.sin_family = AF_INET;
upnpControl.sin_port = htons(0);
upnpControl.sin_addr.s_addr = INADDR_ANY;
if (bind(discoverSocket, (sockaddr*)&upnpControl, sizeof(upnpControl)) == SOCKET_ERROR)
{
printf("bind failed\n");
close(discoverSocket);
return false;
}
broadcast_addr.sin_family = AF_INET;
broadcast_addr.sin_port = htons(1900);
broadcast_addr.sin_addr.s_addr = inet_addr("239.255.255.250");
for(int i = 0; i < 3; i++)
{
if(sendto(discoverSocket, searchSatIPDevice, strlen(searchSatIPDevice), 0, (sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) == SOCKET_ERROR)
{
//printf("sendto failed\n");
close(discoverSocket);
return false;
}
else
{
usleep(10*100);
}
}
InitDiscoverThread();
return true;
}
void SatIP::ListenSSDPResponse()
{
while(1)
{
char buf[512];
memset(buf, 0, 512);
struct sockaddr_in broadcast_addr;
broadcast_addr.sin_family = AF_INET;
broadcast_addr.sin_port = htons(1900);
broadcast_addr.sin_addr.s_addr = inet_addr("239.255.255.250");
int bcLen = sizeof(broadcast_addr);
//bool bRet = false;
while (recvfrom(discoverSocket, buf, 512, 0, (struct sockaddr*)&broadcast_addr, (socklen_t*)&bcLen) > 0)
{
printf("buf:%s\n",buf);
SATIP_SERVER_DESCRIPTION stServerDesc;
ostringstream ss;
if(strstr(buf, "device:SatIPServer"))
{
int i = 0;
char *deviceIp = strstr(buf, "LOCATION:") + 9; // get xml location including server description
while(deviceIp[i] == ' ') i++; // remove spaces from string
while(!isspace(deviceIp[i]))
{
ss << deviceIp[i];
++i;
}
stServerDesc.location = ss.str().c_str();
printf("location:%s\n",stServerDesc.location.c_str());
ss.str(""); // clear ss
i=0; // clear counter
deviceIp = strstr(buf, "http://") + 7; // get ip address
while(deviceIp[i] != ':')
{
ss << deviceIp[i];
++i;
}
stServerDesc.ipAddr = ss.str().c_str();
printf("ipAddr:%s\n", stServerDesc.ipAddr.c_str());
DownloadDeviceDescription(&stServerDesc);
stServerDesc.macAddr = GetMACAddressviaIP(stServerDesc.ipAddr);
printf("macAddr:%s\n", stServerDesc.macAddr.c_str());
if(IsServerProperToAdd(&stServerDesc))
vSatIPServers.push_back(stServerDesc);
printf("\n");
//bRet = true;
}
memset(buf, 0, 512);
}
}
}
How can I fix this issue? Any help would be appreciated.
Listening SSDP notify message is not related to sending M-SEARCH message. Devices like Sat>IP send NOTIFY message to 239.255.255.250 periodically even if you don't send M-SEARCH message. So, you should join a multicast group and receives from the group.
You can use the listener program in the following link by changing HELLO_PORT as 1900 and HELLO_GROUP as "239.255.255.250".
http://ntrg.cs.tcd.ie/undergrad/4ba2/multicast/antony/example.html
/*
* listener.c -- joins a multicast group and echoes all data it receives from
* the group to its stdout...
*
* Antony Courtney, 25/11/94
* Modified by: Frédéric Bastien (25/03/04)
* to compile without warning and work correctly
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define HELLO_PORT 1900
#define HELLO_GROUP "239.255.255.250"
#define MSGBUFSIZE 256
main(int argc, char *argv[])
{
struct sockaddr_in addr;
int fd, nbytes,addrlen;
struct ip_mreq mreq;
char msgbuf[MSGBUFSIZE];
u_int yes=1; /*** MODIFICATION TO ORIGINAL */
/* create what looks like an ordinary UDP socket */
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
perror("socket");
exit(1);
}
/**** MODIFICATION TO ORIGINAL */
/* allow multiple sockets to use the same PORT number */
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
perror("Reusing ADDR failed");
exit(1);
}
/*** END OF MODIFICATION TO ORIGINAL */
/* set up destination address */
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY); /* N.B.: differs from sender */
addr.sin_port=htons(HELLO_PORT);
/* bind to receive address */
if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
perror("bind");
exit(1);
}
/* use setsockopt() to request that the kernel join a multicast group */
mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
mreq.imr_interface.s_addr=htonl(INADDR_ANY);
if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
perror("setsockopt");
exit(1);
}
/* now just enter a read-print loop */
while (1) {
addrlen=sizeof(addr);
if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,
(struct sockaddr *) &addr,&addrlen)) < 0) {
perror("recvfrom");
exit(1);
}
puts(msgbuf);
}
}

USB applications using libusb library

I want to use libusb library for writing some test applications for USB.
Can any one please suggest how to set control transfers using usb_control_msg call?
I am getting bad descriptor error while running the following code.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "usb.h"
static int vendor_id;
static int product_id;
typedef struct{
int requesttype;
int request;
int value;
int index;
char *bytes;
int size;
int timeout;
}ctrlmsg_param;
void print_endpoint(struct usb_endpoint_descriptor *endpoint)
{
printf("=====End point Information====\n");
printf("bEndpointAddress: %x\n", endpoint->bEndpointAddress);
printf("bmAttributes: %x\n", endpoint->bmAttributes);
printf("wMaxPacketSize: %d\n", endpoint->wMaxPacketSize);
printf("bInterval: %d\n", endpoint->bInterval);
printf("bRefresh: %d\n", endpoint->bRefresh);
printf("bSynchAddress: %d\n", endpoint->bSynchAddress);
}
void print_altsetting(struct usb_interface_descriptor *interface)
{
int i;
printf("\n=====Alternate Setting Information====\n");
printf("bInterfaceNumber: %d\n", interface->bInterfaceNumber);
printf("bAlternateSetting: %d\n", interface->bAlternateSetting);
printf("bNumEndpoints: %d\n", interface->bNumEndpoints);
printf("bInterfaceClass: %d\n", interface->bInterfaceClass);
printf("bInterfaceSubClass: %d\n", interface->bInterfaceSubClass);
printf("bInterfaceProtocol: %d\n", interface->bInterfaceProtocol);
printf("iInterface: %d\n", interface->iInterface);
for (i = 0; i < interface->bNumEndpoints; i++)
print_endpoint(&interface->endpoint[i]);
}
void print_interface(struct usb_interface *interface)
{
int i;
for (i = 0; i < interface->num_altsetting; i++)
print_altsetting(&interface->altsetting[i]);
}
void print_configuration(struct usb_config_descriptor *config)
{
int i;
printf("=====Configuration Information====\n");
printf("wTotalLength: %d\n", config->wTotalLength);
printf("bNumInterfaces: %d\n", config->bNumInterfaces);
printf("bConfigurationValue: %d\n", config->bConfigurationValue);
printf("iConfiguration: %d\n", config->iConfiguration);
printf("bmAttributes: %x\n", config->bmAttributes);
printf("MaxPower: %d\n", config->MaxPower);
for (i = 0; i < config->bNumInterfaces; i++)
print_interface(&config->interface[i]);
}
int print_device(struct usb_device *dev)
{
usb_dev_handle *udev;
char str[100];
int ret, i;
udev = usb_open(dev);
if (udev) {
if (dev->descriptor.iManufacturer) {
ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer, str, sizeof(str));
if (ret > 0)
{
printf("Manufacturer is %s\n",str);
}
}
if (dev->descriptor.iProduct) {
ret = usb_get_string_simple(udev, dev->descriptor.iProduct, str, sizeof(str));
if (ret > 0)
{
printf("Product is %s\n",str);
}
}
}
if (udev)
usb_close(udev);
printf("Possible configurations are %x\n",dev->descriptor.bNumConfigurations);
sleep(2);
for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
print_configuration(&dev->config[i]);
return 0;
}
int htod( const char* str )
{
int decimal;
sscanf( str, "%x", &decimal);
return decimal;
}
void set_data(struct usb_device *dev)
{
ctrlmsg_param param;
param.requesttype= 0;
param.request=0;
param.value=0;
param.index=0;
param.bytes=10;
param.size=0;
param.timeout=5000;
usb_control_msg(dev, param.requesttype, param.request, param.value, param.index, param.bytes, param.size, param.timeout);
printf("error is %s\n",strerror(errno));
return;
}
int main(int argc, char *argv[])
{
struct usb_bus *bus;
struct usb_device *dev;
if(argc != 3)
{
printf("Error in number of arguments\n");
printf("Usage:./usb_info <vendor id> <product id>\n");
exit(0);
}
vendor_id=htod(argv[1]);
product_id=htod(argv[2]);
printf("initializing USB library\n");
usb_init();
printf("Finding Buses and Devices\n");
usb_find_busses();
usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) {
if ((dev->descriptor.idProduct == product_id) && (dev->descriptor.idVendor == vendor_id)){
printf("Found device with produxt id %x and vendor id %x\n",product_id,vendor_id);
print_device(dev);
set_data(dev);
print_device(dev);
}
}
}
return 0;
}
Regards,
Sandeep
I think that you mean usb_control_msg() is returns an error code for "bad descriptor". Please clarify if this is incorrect.
USB control transfers have some very specific formatting rules, and if the packet you are forming is sent to any compliant device, it will return a request error / stall on the bus.
You are sending the control transfer:
bmRequestType = 0x00
bRequest = 0x00
wValue = 0x0000
wIndex = 0x0000
wSize = 0x0000
this should be interpreted by the USB device as a GET_STATUS request, so wLength is required to be 2, and bmRequestType needs to have the top bit set, indicating this is an IN direction request (from the host's point of view). This is all from Chapter 9 of the USB specification 1.1/2.0/3.1 available at www.usb.org.
The parameter char *bytes (your param.bytes) also needs to be an address/pointer in the call you are making.
A good standard control transfer to test with would be:
bmRequestType = 0x80
bRequest = 0x06
wValue = 0x0001
wIndex = 0x0000
wSize = 0x0008
This request will return the first 8 bytes of the Device Descriptor, it is valid for every USB device, in all states.
The other transfer types (bulk, interrupt) don't have these strict formatting rules, and can be an easier place to start. I'd imagine you have already moved past this issue, since the question has been posted for quite a while, but maybe this response will still help someone else.