Connect to Acquisition unit(WIFI device) from iPhone/iPad programmatically - ios

I have a hardware device Acquisition unit. This device itself act as wifi router and it will send data. I want to connect it from iPhone/iPad.
I heard that using IP address and port number we can connect to the wifi router using socket programming. But I don't have any idea about this socket program to connect to the wifi using IP address and port number.
For this I have tried to get the IP address of a connected wifi router using following code.
NSString *address = #"error";
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
int success = 0;
// retrieve the current interfaces - returns 0 on success
success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while(temp_addr != NULL) {
if(temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
if([[NSString stringWithUTF8String:temp_addr->ifa_name] isEqualToString:#"en0"]) {
// Get NSString from C String
address = [NSString stringWithUTF8String:inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr)];
}
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
return address;
If it is possible to connect to the wifi router using ip address and port number could you please help me with some code or idea.
Please help me..
Thanks

The code you pasted basically returns the device's own IP address, which does not help at all, unless you want to guess router's IPs. You actually can get correct router IP address, see questions below:
Objective-C : How to fetch the router address?
How to get Wi-Fi router IP address on iOS?
Is it possible to get the SSID & MAC Address of Currently connected WiFi Network in an App
After you have this, you can easily connect to it via a normal TCP/IP connection socket, see the following links for more information:
Socket Connection in IOS
http://www.raywenderlich.com/3932/networking-tutorial-for-ios-how-to-create-a-socket-based-iphone-app-and-server
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/UsingSocketsandSocketStreams.html
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Streams/Articles/NetworkStreams.html
Or to make things even easier for you, there are a couple of community libraries that will make connecting to a server like a breeze:
https://github.com/pkyeck/socket.IO-objc
https://github.com/dreese/FastSocket
My suggestion is to read through those documents first, so you understand the basics of networking in iOS / OS X (which is actually fairly similar to Unix in this aspect). After try the libraries and wrappers you can find on CocoaPods and GitHub. If you are stopped by some specific issue at that point, we might be able to help you. We cannot do all the work for you.
So to answer: Yes, it is possible.

Related

How can I use Bonjour on iOS to let other devices connected to my iPhones hotspot know the ip address and port of the server my iOS app is hosting?

I have created an iOS app that hosts a UDP Server. It doesn't seem possible for me to know the IP address of the server before hand. I use this function to get the IP Address:
// Get IP Addresses
void getIPAddresses(std::map<std::string, std::string>& addresses) {
struct ifaddrs *interfaces = NULL;
struct ifaddrs *temp_addr = NULL;
// Retrieve the current interfaces - returns 0 on success
int success = getifaddrs(&interfaces);
if (success == 0) {
// Loop through linked list of interfaces
temp_addr = interfaces;
while (temp_addr != NULL) {
if (temp_addr->ifa_addr->sa_family == AF_INET) {
// Check if interface is en0 which is the wifi connection on the iPhone
addresses[temp_addr->ifa_name] = inet_ntoa(((struct sockaddr_in *)temp_addr->ifa_addr)->sin_addr);
}
temp_addr = temp_addr->ifa_next;
}
}
// Free memory
freeifaddrs(interfaces);
}
As can be seen this function returns an number of IP addresses and without trial and error it doesn't seem possible to determine which IP address the server actually receives UDP packets on.
Is there some way I can do this better using Bonjour ? The devices that connect to my UDP Server can do so because my iPhone acts as a Wifi Hotspot (I share the SSID and Password to the devices in advance).
EDIT:
It seems that whenever I create an Wifi Hotpspot, the UDP Server is accessible on the interface called "Bridge100". So I know what the iP address is. How can I use Bonjour so that other devices connected to my iPhones Wifi Hotspot can know the iP address of my udp server ?

How to check the Limited Access on wifi in swift, like if my device is connected to wifi but that wifi don't have internet connection

I wanted to check if the wifi has an internet connection or not. Most of the solutions/methods including the alamofire return true only if the device is connected to wifi only, don't check if wifi has an internet connection or not.
Apple's reachability sample code only allows to get info if an interface is available that might allow a connection. There are some endpoints hosted by Apple for verifying if internet access is available. For example this one. You can create your own wrapper on top of Apple's reachability or use existing one called Connectivity. It provides you such options:
connectedViaWiFi,
connectedViaWWAN,
connectedViaWiFiWithoutInternet,
connectedViaWWANWithoutInternet
You are interesting on connectedViaWiFiWithoutInternet and connectedViaWWANWithoutInternet. This library allow to configure which end points to use, etc.
Simply do:
var reachabilityManager = NetworkReachabilityManager()
private
var networkIsReachable : Bool{
return reachabilityManager?.isReachable ?? false
}
private
var isEthernetOrWifiReachable : Bool{
return reachabilityManager?.isReachableOnEthernetOrWiFi ?? false
}
Since there is no ethernet on mobiles isReachableOnEthernetOrWiFi will check for wifi

iPhone: IPv4 Wi-Fi access fails with cellular radio enabled

I've got an iPhone app that makes UPnP queries over Wi-Fi to locate a Wi-Fi-connected camera, using GCDAsyncSocket. All the communications use IPv4 addresses over an ad-hoc network created by the cameras themselves, and the app is working properly with over 2500 field deployments.
However I have one customer for whom it fails on his iPhone, unless Airplane Mode is on, or cellular data is turned off. The same camera works fine with his iPad mini, so it's not the camera's fault as best we can determine.
The app sets up a listening socket:
_listenSocket = [[GCDAsyncSocket alloc] initWithDelegate:self
delegateQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)];
_listenSocket.IPv6Enabled = NO;
accepted = [_listenSocket acceptOnInterface:getWirelessInterface()
port:_upnpPort error:&error];
It then sets up a sending socket, also with IPV6 disabled; connects to the host (at a known or suspected IP address) over the wireless interface; and sends a UPnP SUBSCRIBE message:
_sendSocket = [[GCDAsyncSocket alloc] initWithDelegate:self
delegateQueue:dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)];
if (!_sendSocket) {
NSLog(#"sendMsg: unable to allocate sendSocket");
return;
}
_sendSocket.IPv6Enabled = NO;
NSError *err = nil;
if (![_sendSocket connectToHost:hostParts[0]
onPort:[hostParts[1] intValue]
viaInterface:getWirelessInterface()
withTimeout:TIMEOUT
error:&err]) // Asynchronous!
{
// If there was an error, it's likely something like
// "already connected" or "no delegate set"
NSLog(#"socket connectToHost error: %#", err);
return;
}
[_sendSocket writeData:[msg dataUsingEncoding:NSUTF8StringEncoding] withTimeout:TIMEOUT tag:1];
Normally, this works as expected. However, in this one case, the send fails; the delegate method socketDidDisconnect:withError: gets called:
sendSocket disconnected with error: Error Domain=GCDAsyncSocketErrorDomain
Code=8 "IPv6 has been disabled and DNS lookup found no IPv4 address."
If I delete the "xxxSocket.IPv6Enabled = NO;" lines, I get this instead:
listenSocket disconnected with error: Error Domain=NSPOSIXErrorDomain
Code=65 "No route to host"
Various Googlings indicate that "no route to host" indicates an IPv4 address can't be resolved in an IPv6 environment, and the "IPv6 has been disabled and DNS lookup found no IPv4 address" message is self-explanatory.
Why is this happening on this one iPhone, and not on all the others out there (including my own test instruments)? How might I fix it, aside from saying "turn cellular data off"? Why is DNS even involved, if I'm using the IPv4 address of the very router (ad-hoc access point) I've already connected to to get the network running in the first place?
(One other stackoverflow post (GCDAsyncUdpSocket immediately closes when sending to an IPv6 address) suggested retrying until things worked, but I haven't had any success with that.)
I haven't been able to figure out why this is happening: it affects at least two people on T-Mobile in Florida and California, but I can't replicate it using T-Mobile in Washington.
I did find a fix: replace connectToHost with connectToAddress, which connects to the IPv4 address directly without a DNS resolution step. While connectToHost allows either a hostname or an IP address, it runs a DNS lookup step even with an IP address, and that lookup was getting confounded by whatever was occurring when the affected iDevices were connected to T-Mobile.

ESP8266: Wifi gets connected, but no internet access

I am trying to connect my ESP8266 NodeMCU to my Mobile Hotspot Wifi
When I try to connect to the ESP Wifi using laptop, It says Wifi Connected, no Internet access.
Which means, The Wifi_SSID and Password are fetched by ESP correctly.
Why is the ESP not able to connect to the Internet?
I have used Arduino IDE for uploading code to ESP8266.
I have uploaded the below code to the ESP8266.
#include <FirebaseArduino.h>
#include <ESP8266WiFi.h>
// Set these to run example.
#define WIFI_SSID "OnePlus3"
#define WIFI_PASSWORD ""
#define FIREBASE_DB_URL "https://my_db_url.firebaseio.com/"
#define FIREBASE_DB_SECRET_KEY "fakezaSyDsdadasddwGClaAy8ltYgywwo6i_VzXgY"
void setup() {
Serial.begin(115200);
pinMode(D1, OUTPUT);
pinMode(D2, OUTPUT);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
Firebase.begin(FIREBASE_DB_URL, FIREBASE_DB_SECRET_KEY);
Firebase.stream("/automation");
}
void loop() {
if (Firebase.failed()) {
Serial.println("streaming error");
Serial.println(Firebase.error());
}
if (Firebase.available()) {
FirebaseObject event = Firebase.readEvent();
String eventType = event.getString("type");
eventType.toLowerCase();
Serial.print(eventType);
if (eventType == "put") {
String path = event.getString("path");
String data = event.getString("data");
if (path.equals("/fan/value")) {
if (data.equals("off")) {
digitalWrite(D1, HIGH);
} else {
digitalWrite(D1, LOW);
}
} else if (path.equals("/light/value")) {
if (data.equals("off")) {
digitalWrite(D2, HIGH);
} else {
digitalWrite(D2, LOW);
}
}
}
}
}
Troubleshooting ESP8266 not connecting to WiFi
Failure to connect to the WiFi network can be caused by some factors. Among them I highlight:
1 - The ESP8266 has a particularity of the initial state of its GPIOs during an initialization. As the intention is to make a connection to the Internet, I suggest that you leave the ESP8266 only with the power and communication connections. If you have a NodeMCU you can use only the USB cable.
2 - Wrong filling in of the access data of the router will cause an error in the connection. Please note that you have to put in your code the WLAN SSID and WLAN PASS information, which are, respectively, the name and password of your network. It is worth remembering that the capture of these characters is case sensitive.
3 - If your router is not connected to the Internet, then you will have feedback via the serial monitor of your local IP, but you will not have confirmation of access with the Google server. Test it with your smartphone or computer and check if everything is fine with your Internet connection.
4 - It is difficult, but I have already seen incompatibility with the internet provider. To solve, test on different networks. I suggest that we carry out tests with your smartphone functioning as a WiFi router. You can even check the connected devices quickly and easily.
You can learn more about it in this link (Eduardo Castro) in Brazilian Portuguese:
https://www.filipeflop.com/blog/como-conectar-o-esp8266-a-internet/

IOS boost asio connect from ipv6 network

I am trying to connect a dvr using boost asio library in ios. The application works fine in emulator with in ipv4 network. But when I submit the application on Appstore apple rejected the application as it's not work on ipv6 network. And I can see in the apple site that application should support ipv6 network. https://developer.apple.com/news/?id=05042016a
So I think the problem comes at the section where I am trying to connect to DVR using boost library, where the ip address of the DVR is pulled from DB(hard-coded) and below is the relevant part of the code.
boost::asio::io_service io_service_;
tcp::resolver::iterator endpoint_iter_;
tcp::resolver resolver_; //to healp resolving hostname and ip
stringstream strstream;//create a stringstream
strstream << port;//add number to the stream
endpoint_iter_ = resolver_.resolve(tcp::resolver::query(ip.c_str(),strstream.str()));
start_connect(endpoint_iter_);
// Start the deadline actor. You will note that we're not setting any
// particular deadline here. Instead, the connect and input actors will
// update the deadline prior to each asynchronous operation.
deadline_timer_.async_wait(boost::bind(&dvr_obj::check_deadline, this));
//starting thread for dvr connection
io_service_.reset();
thread_ = new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service_));
start_connect method
void start_connect(tcp::resolver::iterator endpoint_iter)
{
try
{
if (endpoint_iter != tcp::resolver::iterator())
{
drill_debug_info("trying to connect %s \n",name.c_str());
// Set a deadline for the connect operation.
deadline_timer_.expires_from_now(boost::posix_time::seconds(10));
// Start the asynchronous connect operation.
socket_.async_connect(endpoint_iter->endpoint(),
boost::bind(&dvr_obj::handle_connect,
this, _1, endpoint_iter));
}
else
{
// There are no more endpoints to try. Shut down the client.
connectivity = false;
}
} catch (int e) {
connectivity = false;
}
}
So I am confused how to change above code to work on IPV6 network. Could not find any solution in Internet.
You can iterate through the endpoints to find an IPv6 endpoint using the code below:
endpoint_iter_ = resolver_.resolve(tcp::resolver::query(ip.c_str(),strstream.str()));
while (endpoint_iter_ != tcp::resolver::iterator())
{
if (endpoint_iter_->endpoint().protocol() == tcp::v6())
break;
++endpoint_iter_;
}
if (endpoint_iter_ != tcp::resolver::iterator())
{
start_connect(endpoint_iter_);
...
}
else
std::cerr << "IPv6 host not found" << std::endl;

Resources