I need to make a simple GET call using HTTP. Despite successfully connecting to the WiFi network, getting the IP, Gateway and DNS correctly, The HTTP client keeps getting connection failed error. I tried using the WiFi client as well but no luck. It don't think the issue is with my code, I tried to use the code from the examples folder as well and it fails too. I tried connecting to a local internal server and it failed. I have spent about a whole day on this and I can't figure what could be wrong.
The code is given below. That is all there is at the moment.
I am using the Arduino for ESPRESSIF on Platform IO using Visual Code Editor on Windows.
The WifiConnect function is called from setup()
Initially I was only calling the WiFi.begin() function to connect which was also connecting with the WiFi but since the connection kept failing I tried ESP8266WiFiMulti as per the sample code.
I even checked that host name resolution also works
IPAddress remote_addr;
WiFi.hostByName("192.168.2.107", remote_addr);
Serial.println(remote_addr);
But connecting to any server always fails. I've tried connecting to servers internal to the network, servers on the internet, servers running http on special ports, normal port 80 etc. But it stubbornly refuses to connect.
#include "Arduino.h"
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include "Ticker.h"
#include <WiFiClient.h>
#include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti WiFiMulti;
void WifiConnect()
{
WiFi.mode(WIFI_STA);
WiFiMulti.addAP("MySSID", "MySECret Password");
Serial.print("Connecting");
while (WiFiMulti.run() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
Serial.println(WiFi.dnsIP());
Serial.println(WiFi.gatewayIP());
Serial1.println(WiFi.localIP());
}
void logToThinkSpeakt(){
// wait for WiFi connection
if ((WiFiMulti.run() == WL_CONNECTED)) {
WiFiClient client;
HTTPClient http;
Serial.print("[HTTP] begin...\n");
if (http.begin(client, "http://jigsaw.w3.org/HTTP/connection.html")) { // HTTP
Serial.print("[HTTP] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = http.getString();
Serial.println(payload);
}
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
} else {
Serial.printf("[HTTP} Unable to connect\n");
}
}
}
PLATFORM: Espressif 8266 2.6.2 > NodeMCU 1.0 (ESP-12E Module)
HARDWARE: ESP8266 80MHz, 80KB RAM, 4MB Flash
PACKAGES:
framework-arduinoespressif8266 3.20704.0 (2.7.4)
tool-esptool 1.413.0 (4.13)
tool-esptoolpy 1.20800.0 (2.8.0)
tool-mklittlefs 1.203.200522 (2.3)
tool-mkspiffs 1.200.0 (2.0)
toolchain-xtensa 2.40802.200502 (4.8.2)
LDF: Library Dependency Finder
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 29 compatible libraries
Scanning dependencies...
Dependency Graph
|-- 1.0
|-- 1.2
| |-- 1.0
|-- 1.0
Building in release mode
Related
I am looking for a way to get the device IP that is not based on Wifi. I am unable to find the local IP of the current device when compiling to Linux app running on an ethernet connection with no wifi card.
I tried using 'package:wifi/wifi.dart' and 'package:network_info_plus/network_info_plus.dart' to get the device's local ip and both packages gave this error: MissingPluginException (MissingPluginException(No implementation found for method ip on channel plugins.ly.com/wifi))
Is there a way to get the device local IP without a Wifi card?
UPDATE:
Using https://stackoverflow.com/a/52411510/5861729 and https://stackoverflow.com/a/43803986/16477035 I was able to figure out a clean way to get my local ip.
// Find localIp
String localIp = '';
final List<String> privateNetworkMasks = ['10', '172.16', '192.168'];
for (var interface in await NetworkInterface.list()) {
for (var addr in interface.addresses) {
for (final possibleMask in privateNetworkMasks) {
if (addr.address.startsWith(possibleMask)) {
localIp = addr.address;
break;
}
}
}
}
Run 'flutter clean' then 'flutter pub get' and re install your app
I am trying to setup a basic example of sending a message from the Arduino MKR1000 to the Azure IOT Event Hub but can't seem to get any of the online examples to work and I am new to Arduino.
Any pointers for a simple working example?
I tried this example and changing slightly to POST a message rather than receive but no luck. I can connect to the Wifi with no issues, its just when posting the HTTP request it errors with "HTTP Error 411. The request must be chunked or have a content length". It also doesn't seem like the most clean approach but I just wan't to get something basic up and running for now to play with :)
Code Example:
#include <SPI.h>
#include <WiFi101.h>
#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
const int MKR1000_LED = 6 ;
///*** Azure IoT Hub Config ***///
//see: http://mohanp.com/ for details on getting this right if you are not sure.
char hostname[] = "*****.azure-devices.net"; // host name address for your Azure IoT Hub
char feeduri[] = "/devices/MKR1000/messages/events?api-version=2018-06-30"; //feed URI
char authSAS[] = "SharedAccessSignature sr=******.azure-devices.net%2Fdevices%2FMKR1000&sig=*****&se=******";
///*** Azure IoT Hub Config ***///
unsigned long lastConnectionTime = 0;
const unsigned long pollingInterval = 5L * 1000L; // 5 sec polling delay, in milliseconds
int status = WL_IDLE_STATUS;
WiFiSSLClient client;
void setup() {
Serial.println("setup...");
pinMode(MKR1000_LED, OUTPUT);
//check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
// don't continue:
while (true);
}
// attempt to connect to Wifi network:
while (status != WL_CONNECTED) {
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Wifi connected...");
}
void loop()
{
String response = "";
char c;
///read response if WiFi Client is available
while (client.available()) {
c = client.read();
response.concat(c);
}
if (!response.equals(""))
{
Serial.println(response);
//if there are no messages in the IoT Hub Device queue, Azure will return 204 status code.
if (response.startsWith("HTTP/1.1 204"))
{
//turn off onboard LED
digitalWrite(MKR1000_LED, LOW);
}
else
{
//turn on onboard LED
digitalWrite(MKR1000_LED, HIGH);
}
}
// polling..if pollingInterval has passed
if (millis() - lastConnectionTime > pollingInterval) {
digitalWrite(MKR1000_LED, LOW);
azureHttpRequest("{TEST MESSAGE!}");
}
}
// this method makes an HTTPS connection to the Azure IOT Hub Server:
void azureHttpRequest(String data) {
// close any connection before send a new request.
// This will free the socket on the WiFi shield
client.stop();
// if there's a successful connection:
if (client.connect(hostname, 443)) {
//make the GET request to the Azure IOT device feed uri
client.print("POST "); //Do a GET
client.print(feeduri); // On the feedURI
client.println(" HTTP/1.1");
client.print("Host: ");
client.println(hostname); //with hostname header
client.print("Authorization: ");
client.println(authSAS); //Authorization SAS token obtained from Azure IoT device explorer
//client.println("Connection: close");
client.println("Content-Type: application/json");
client.println("Content-Length: " + data.length());
client.println("\r\n\r\n" + data);
// note the time that the connection was made:
lastConnectionTime = millis();
}
else {
// if you couldn't make a connection:
Serial.println("connection failed");
}
}
Edit: I have seen that there is a full Azure IOT library with a simple HTTP example, but this also doesn't run (it gets passed the wifi connection and failing with call to azure) but this example project is fairly large and I was hoping for a simple example to build upon!
https://github.com/Azure/azure-iot-arduino
I followed the following tutorial: http://www.pubnub.com/blog/pubnub-streaming-texas-instruments-iot/
step by step and I managed to compile and code and connect to my Wi-Fi access point.
I think I managed to connect to PubNub (the code prints on the terminal screen "PubNub Set Up" but in the code there is no real verification that it was indeed set up.
I opened an account on PubNub and I named my channel "testing" (I named it the same in the code I uploaded - I checked that a million times) and when I go to the Dev Console and click on subscribe I can't see anything! I mean I can post messages through the Dev Console but what I really want to see are the messages from the CC3100.
I checked the UART terminal on my computer and I see the data being printed constantly so I know it is working.
I went over the tutorial again and again and I'm doing the same thing but it just doesn't work.
Any help would be appreciated!
What am I missing?
Thanks
First to verify your PubNub account is properly configured and your local Wi-Fi connectivity is working - are you able to publish messages from the dev console in one browser and receive them in the dev console on another browser? (both using the same channel name, of course). If that works, please send a message to help (at) pubnub (dot) com with your sub-key info and information about your project and we will try to assist you tracking down the issue.
This answer is posted really late. I admit I forgot about this post so I just decided to update it (a few years late though).
I started digging to try and see what was the problem and I think I found it. First of all, I saw that PubNub.publish() wasn't working properly with the json_String because the json_String was 90% gibrish. So I erased most of the code that constructed the json_String (the part that inserts the analog values) and made it simpler.
I then also added a part of code at the end which was needed for proper performance of the client variable which I got off of a part of code which was used for an arduino based project using the CC3100.
Anyway, the new code is the one below and now it works FINE! I finally see all the input streaming on PubNub! Thanks a lot! :D
/*PubNub sample JSON-parsing client with WiFi support
This combines two sketches: the PubNubJson example of PubNub library
and the WifiWebClientRepeating example of the WiFi library.
This sample client will properly parse JSON-encoded PubNub subscription
replies using the aJson library. It will send a simple message, then
properly parsing and inspecting a subscription message received back.
This is achieved by integration with the aJson library. You will need
a version featuring Wiring Stream integration, that can be found
at http://github.com/pasky/aJson as of 2013-05-30.
Please refer to the PubNubJson example description for some important
notes, especially regarding memory saving on Arduino Uno/Duemilanove.
You can also save some RAM by not using WiFi password protection.
created 30 May 2013
by Petr Baudis
https://github.com/pubnub/pubnub-api/tree/master/arduino
This code is in the public domain.
*/
#include <SPI.h>
#include <WiFi.h>
#include <PubNub.h>
#include <aJSON.h>
static char ssid[] = "NetSSID_Name"; // your network SSID (name)
static char pass[] = "NetworkdPassword"; // your network password
static int keyIndex = 0; // your network key Index number (needed only for WEP)
const static char pubkey[] = "pub-c-51eb45ec-b647-44da-b2aa-9bf6b0b98705";
const static char subkey[] = "sub-c-7e78ed9c-991d-11e4-9946-02ee2ddab7fe";
const static char channel[] = "testing";
#define NUM_CHANNELS 4 // How many analog channels do you want to read?
const static uint8_t analog_pins[] = {23, 24, 25, 26}; // which pins are you reading?
void setup()
{
Serial.begin(9600);
Serial.println("Start WiFi");
WiFi.begin(ssid, pass);
while(WiFi.localIP() == INADDR_NONE) {
Serial.print(".");
delay(300);
}
Serial.println("WiFi set up");
PubNub.begin(pubkey, subkey);
Serial.println("PubNub set up");
delay(5000);
}
void loop()
{
WiFiClient *client;
// create JSON objects
aJsonObject *msg, *analogReadings;
msg = aJson.createObject();
aJson.addItemToObject(msg, "analogReadings", analogReadings = aJson.createObject());
// get latest sensor values then add to JSON message
/*for (int i = 0; i < NUM_CHANNELS; i++) {
String analogChannel = String(analog_pins[i]);
char charBuf[analogChannel.length()+1];
analogChannel.toCharArray(charBuf, analogChannel.length()+1);
int analogValues = analogRead(analog_pins[i]);
aJson.addNumberToObject(analogReadings, charBuf, analogValues);
}*/
// convert JSON object into char array, then delete JSON object
char *json_String = aJson.print(msg);
aJson.deleteItem(msg);
// publish JSON formatted char array to PubNub
Serial.print("publishing a message: ");
Serial.println(json_String);
Serial.println(channel);
client = PubNub.publish(channel, json_String);
Serial.println(*client);
free(json_String);
if (!client) {
Serial.println("publishing error");
delay(1000);
return;
}
client->stop();
delay(500);
}
//- See more at: http://www.pubnub.com/blog/pubnub-streaming-texas-instruments-iot/#sthash.tbQXMIzw.dpuf
This is a C++ server application which communicates with all clients based on UDP protocol. When a user logs into the server from client, the client application registers a UDP channel to the server and this channel is in fixed format: IP+Port, which means if the IP keeps unchanged, then no matter what user logged in the client registers a same channel.
The server's socket layer maintains a heartbeat mechanism which will remove the channel if it doesn't receive any heartbeat packets from the channel in 3 minutes. Everything works fine until the client is down, e.g. the network wire is plugged off. Look at below scene:
1. User-A logs into server. The Client registers channel (IP:Port)
to the server. Because the UDP channel is alive, so the Server
sets the User status of User-A as Online.
2. Kill the client process, and within 3 minutes(before the channel
timeouts in server), let User-B logs into server from the same
computer. Because the IP remains unchanged, so actually the client
registers a same (IP:PORT) pair to the server as it did when User-A
logs in.
3. Since the Server receives packets from (IP:PORT), so it considers
User-A is still alive, thus setting the user status of User-A as
Online which is not right anymore.
In above scenario, the Server is not able distinguish different users logged from a same computer, which results in wrong user states. Does anybody know how to solve this problem?
I see no reason to presume that the origin port number for any two users will be identical unless the client application is explicitly binding the UDP socket. Clients which initiate the communication can often use ephemeral ports just as effectively. Ephemeral ports may or may not be sufficiently random for your particular use case, code below shows how to access client ports from inbound UDP data. If they are not sufficiently random, it may be wise to encode session cookies or user-cookies into the protocol.
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
int
main() {
/*- setup UDP socket on 8500 */
int rc;
int server_socket;
struct sockaddr_in server_address;
server_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (server_socket < 0) {
perror("failed to init socket");
return 1;
}
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(8500);
server_address.sin_addr.s_addr = inet_addr("127.0.0.1");
rc = bind(server_socket, (struct sockaddr*) &server_address
, sizeof(server_address));
if (rc < 0) {
perror("failed to bind");
return 2;
}
/* - receive from UDP socket and print out origin port - */
char buffer[4096];
struct sockaddr_in client_address;
int client_address_len = sizeof(client_address);
rc = recvfrom(server_socket
, buffer
, sizeof(buffer)
, 0
, (struct sockaddr*) &client_address
, &client_address_len);
if (rc < 0)
return 3;
fprintf(stderr, "%s %d\n", buffer, ntohs(client_address.sin_port));
return 0;
}
I am trying to develop a Video Client/functionality that captures video using webcam and transfers to other servent (server-client) somewhere on the internet. I am using UDPCLient Class to do that.
I want my application to be able to listen and tarnsmit video captured from webcam. The capturing, transmission and receiving works fine when i do that on local network.
But when i test the application from behind router (across two differnt networks/internet) after forwarding respective ports, the internet connectivity is lost on both routers (They hang up or something) and i need to restart the routers or switch to an alternate connection. The configuration is as follows:
Servent 1 <--> Router1 <--> Internet Connection#01
Servent 02 <---> Router2 <---> Internet Connection#02
Both connections are on separate DSL Line. One of the routers is ZTE brand and the other is of Netgear.
Code for listenning/transmission is as follows:
private void StartSockets()
{
//For testing across internet i use IPAddress obtained via different function
var IPAddress = getMyIpAddress();
this.udpSender = new UdpClient(IpAddress, 4000);
this.udpListener = new UdpClient(4000);
}
private IPAddress getMyIpAddress()
{
IPAddress localIP ;//= AddressAr[0];
localIP = IPAddress.Parse(GetPublicIP());
return localIP;
}
public string GetPublicIP()
{
String direction = "";
WebRequest request = WebRequest.Create("http://checkip.dyndns.org/");
using (WebResponse response = request.GetResponse())
{
using (StreamReader stream = new StreamReader(response.GetResponseStream()))
{
direction = stream.ReadToEnd();
}
}
//Search for the ip in the html
int first = direction.IndexOf("Address: ") + 9;
int last = direction.LastIndexOf("</body>");
direction = direction.Substring(first, last - first);
return direction;
}
Code for receiving response is as follows:
private void ReceiveData()
{
//For testing across internet i use IPAddress obtained via different function
var IPAddress = getMyIpAddress();
IPEndPoint ep = new IPEndPoint(IPAddress, myPort);
try
{
byte[] receiveBytes = this.udpListener.Receive(ref ep);
this.OnReadImage(new ImageEventArgs(this.ByteToImage(receiveBytes)));
}
catch (Exception)
{
}
}
If i test on local network , i use DNSHostname to get ip address (private ip addresses) and video works fine on local network. That does not work over internet so i switch to live Ip Address and thus i use the method of getPublicIpAddress().
I know there is something seriously wrong with my approach? What would be right approach?
Should i switch to TCP Listenner? I intend to have multiple receiver of same video in future. So would that affect?
Can UDP clients cause routers to crash, hang up and restart? How can i avoid that?
Lastly, if were to avoid port-forwarding what would be the best strategy?
Please help.
Thanks
Steve