easyMesh icon indicating copy to clipboard operation
easyMesh copied to clipboard

Wifi Client device connections & SSID

Open sfranzyshen opened this issue 8 years ago • 11 comments

The way easyMesh sets itself up ... it doesn't provide or allow for an easy way for wifi client devices to connect (like an android device) to it ... yes each node creates an AP with the mesh name + esp8266 id ... and a client device could connect to anyone of them ... but if the client device connects to one of the APs and that AP fails ... the device is disconnected from the mesh (unless the client device was previously connected to one of the other nodes ... but then the ip changes ...)

If we moved the identity of the nodes from the SSID (and i guess into the protocol itself ... it it's not already there) we could set the SSID's to be all the same for each of the node AP's ... that way ... if one fails ... the client device would attempt to reconnect to one of the other nodes ... right?

could i edit easyMesh.cpp - easyMesh::init(} as follows ...

_mySSID = _meshPrefix + String( _chipId );
_mySSID = _meshPrefix;

with the use of mdns & ssds we could handle name resolution or use a captive dns server to redirect everything ... instead of needing to know the ip address of the connected AP for a web interface ... or is there even a reason for having every AP start it's own unique class c network? since each node to node communication takes place between their own private tcp network connection?

IP4_ADDR( &ip, 192, 168, ( _chipId & 0xFF ), 1); //from easyMeshAP.cpp

when the tcp connection uses the gw address (connected AP) anyway ...

os_memcpy(_stationConn.proto.tcp->remote_ip, &ipconfig.gw, 4); //from easyMeshSTA.cpp

what would happen if every AP had the same ip address ( 192.168.1.1) ??

sfranzyshen avatar Sep 30 '16 23:09 sfranzyshen

Yes!

There is certainly room for improvement on this point. It would be great if all of the wifi networks had the same SSID, and if all of the APs had the same IP address… But there are some thing to consider.

Connecting to wifi, and receiving wifi connections both appear to be rather processor intensive for the esp8266. Because of this I tried to avoid a situation where unnecessary connections were getting made repeatedly, often, systematically, and ad-infinitum. To do this, easyMesh needs to have a way to identify the wifi networks of nodes that it is already connected to before it tries to make a connection. (I say “needs” in the previous sentence, but this is really just how it appears to me right now. I’m super open to suggestions for other approaches)

As I was trying to keep things “easy” I just wacked the chipID onto the SSID.

It seems that there might be a way to do a similar trick using the MAC addresses that are broadcast in the BSSID. Since these are configurable, perhaps the chipId could be used to establish both the AP and the STA MAC addresses in one of the “Locally Administered Address Ranges”. This would likely allow for the use of a single SSID across all nodes.

As for all APs having the same IP address? I don’t know… it would take some research/hacking/experimentation. Clearly, this would not work at all if the esp8266 was acting as a network bridge between the AP and STA… but it is not… entirely. It is not exactly clear to me at the moment how this would be handled by the esp8266, but at the very least I cannot say it is impossible.

I would love to see these or other ideas move forward… I’d love to see some pull requests!

Coopdis avatar Oct 04 '16 22:10 Coopdis

I'm going to try and work out these two issues ... one at at time ... first set all SSIDs to be the same ...

What if we used the bssid (uint8[6]) for the "node id" (chipId) instead of the esp's chipid (uint32[0])?? The size difference is only 16bits (??) ...And if we are going to port this over to run on linux (openwrt, rpi, etc.) and other platforms then we would need to handle the "chipid issue" that would come up anyway ... It should be able to be a unique identifier for all devices ...

it's not clear to me (in the code) how subconnections work ... how it stores (where) the chipid during a STA to an AP connection ... ??????????????????????????????????????????

sfranzyshen avatar Oct 06 '16 21:10 sfranzyshen

I just noticed this in the SDK documentation ...

ESP8266 soft-AP and station have different MAC addresses, please do not set them to be the same.

so ... it looks like we need another mechanism here ... still use the AP's bssid/mac as it's node id (chipId) and get the STA to send it's (AP's) bssid/mac along during the tcp connection as it's node id (chipId) ...

specific APs can be targeted when several APs have the same ssid by setting its bssid in the station_config ...

struct station_config {
uint8 ssid[32];
uint8 password[64];
uint8 bssid_set;
uint8 bssid[6];
}

If station_config.bssid_set==1 then bssid (MAC address of AP) will be used when several APs have the same SSID ... and the bssid is already being stored in the bss_info from the scan ...

struct bss_info {
STAILQ_ENTRY(bss_info) next;
u8 bssid[6];
u8 ssid[32];
u8 channel;
s8 rssi;
u8 authmode;
uint8 is_hidden; // SSID of current AP is hidden or not.
sint16 freq_offset; // AP’s frequency offset
};

sfranzyshen avatar Oct 06 '16 22:10 sfranzyshen

I can not figure out how or when the connecting Station (STA) tells the AP it's ChipID?

I started a separate discussion topic over at esp8266.com

sfranzyshen avatar Oct 07 '16 05:10 sfranzyshen

sfranzyshen,

I think we can get around the requirement that the AP and the STA have different MAC addresses quite easily. chipID is a 32-bit number. MAC address is a 48-bit number. The "locally administered address ranges" are...

x2-xx-xx-xx-xx-xx x6-xx-xx-xx-xx-xx xA-xx-xx-xx-xx-xx xE-xx-xx-xx-xx-xx

... so they are all signified by the second byte. That leaves us 12 bits to play with. If we said that APs would be signified by a 0 and STA would be signified by a 1, then we could do a scheme like this...

chipId = 0xCCCCCCCC

AP MAC = 02-xx-CC-CC-CC-CC STA MAC = 12-xx-CC-CC-CC-CC

This way, both the AP and the STA have unique MAC addresses, which also contain the chipId!.

RE: Unique numbers This is a tricker problem, which I don't think has an easy solution in the "masterless" space.

It is massively convenient that every esp8266 has a unique chipId, but when we port, we are at best going to be picking numbers from a different unique set which is likely to overlap... and therefore we now have to deal with the risk of unique id's "colliding" and not actually being unique after all.

Luckily with a 32bit unique id, the chances of a collision remain pretty small until you get into massive systems. In easyMesh (as is) the size of the system is limited by the amount of available memory on the node with the least memory, so practically systems cannot grow into the 10,000 or 100,000 node range anyway.

Creating a method by which smaller sub-meshes can be automatically established and bridged to one another would solve the scaling issue and mitigate the unique id issue... but with a diversity of platforms, we are still going to need to be able to deal with collisions if they do happen.

This might not be too hard to deal with? If a node is searching, and it sees a WiFi network on the mesh that is already broadcasting it's uniqueId... then it can simply increment it's uniqueId and search again.

Of course, this node would have to shutdown it's AP and restart it with the new uniqueID as well. In some situations, this could cause a fairly significant re-organizing of the mesh... but this situation should only happen once per collision and would likely be rare enough that it can be tolerated.

Thoughts?

Coopdis avatar Oct 07 '16 16:10 Coopdis

any thoughts about how or when the connecting Station (STA) tells the AP about it's ChipID??

While I definitely find the above solution ingenious ... and in an "all esp8266" environment it's probably the ideal solution ... when it comes to porting this (protocol) over to other platforms ... modifying the MAC address(es) may not be (in my opinion) the best approach ...

the beauty of easyMesh (to me) is it's ability to function over out-of-the-box wifi features/functions. I personally see the above solution to be more intrusive (to this basic function) then using the existing AP bssid of each node of the mesh as the unique identifier ...

each node has a unique AP bssid ... and every STA connecting to an AP (somehow?) tells the AP what it's chipID is ... and (during that telling) pass the STA's AP bssid ... (rather than passing the esp's chipID)

UPDATE: It looks like the chipID gets set in handleNodeSync() ...

if ( conn->chipId != remoteChipId ) {
  debugMsg( SYNC, "handleNodeSync(): conn->chipId updated from %d to %d\n", conn->chipId, remoteChipId );
  conn->chipId = remoteChipId;
}

sfranzyshen avatar Oct 07 '16 18:10 sfranzyshen

Currently the STA tells the AP it's chipID in the sync handshake.

This would likely not be necessary in the bssid-MAC scheme.

Coopdis avatar Oct 07 '16 21:10 Coopdis

UPDATE: damn! I over looked the "already connected" check done in connectToBestAP() ... guess i'm back to using the bssid ...

        String apChipId = (char*)ap->ssid + _meshPrefix.length();

        if ( findConnection( apChipId.toInt() ) != NULL )  {
            ap = _meshAPs.erase( ap );
        }
        else {
            ap++;

the chipId from within the SSIDs are used to distinguish between the AP's when making a wifi STA connection only ... and does not pass the chipId on to the STA ... the AP and STA both tell each other about their chipId's by sending their first NodeSync message(s) ... From handleNodeSync()

    if ( conn->chipId != remoteChipId ) {
        debugMsg( SYNC, "handleNodeSync(): conn->chipId updated from %d to %d\n", conn->chipId, remoteChipId );
        conn->chipId = remoteChipId;

    }

changes to connectToBestAP() (easyMeshSTA.cpp) in how it sets up the struct station_config to allow targeting specific APs by using the bssid instead of the ssid ... From:

    struct station_config stationConf;
    stationConf.bssid_set = 0;
    memcpy(&stationConf.ssid, bestAP->ssid, 32);

To:

    struct station_config stationConf;
    stationConf.bssid_set = 1;
    memcpy(&stationConf.bssid, bestAP->bssid, 6);
    memcpy(&stationConf.ssid, bestAP->ssid, 32);

and modifing init() (easyMesh.cpp) to not add the chipId to the ssid ... From: _mySSID = _meshPrefix + String( _chipId ); To: _mySSID = _meshPrefix; and the strncmp() test in stationScanCb() should hold up since they'll still match ... if ( strncmp( (char*)bssInfo->ssid, staticThis->_meshPrefix.c_str(), staticThis->_meshPrefix.length() ) == 0 ) { I like the fact that the exchange of chipId isn't being done at the wifi level ... this keeps it to basic wifi function and allow to port to other platforms ... After further thought about all APs having the same IP (192.168.1.1) might actually work ... since both the IF_STA and the IF_SoftAP have different MAC address ... it should tolerate it since there is no ip routing and both networks are separate ... modifing apInit() (easyMeshAP.cpp) as follows ... From: IP4_ADDR( &ip, 192, 168, ( _chipId & 0xFF ), 1); To: IP4_ADDR( &ip, 192, 168, 1, 1); I haven't had a chance to test any of this ... but it should allow all nodes to use the same ssid ... and maybe all APs having the same ip ...

sfranzyshen avatar Oct 09 '16 23:10 sfranzyshen

here is my solution for having a single ssid for all of the nodes I have submitted a pull request ... here is my current code ... https://github.com/sfranzyshen/easyMesh/tree/devel

I have tested setting all APs to a single IP address ... but it didn't work ...the two nodes stop responding to one another ... although the client wifi device connectes fine ...

sfranzyshen avatar Oct 12 '16 23:10 sfranzyshen

next part for the client device side of stuff is a captive portal with a popup "login to network" dialog ... that opens the user web browser interface ... perform a dns redirect to http://MyMesh ... for example

sfranzyshen avatar Oct 16 '16 04:10 sfranzyshen

@sfranzyshen hey iam make an attempt on your code but it give this error

src\easyMeshConnection.cpp:336:127: error: 'struct meshConnectionType' has no member named 'chipId'

staticThis->debugMsg( COMMUNICATION, "meshRecvCb(): lastRecieved=%u fromId=%d\n", receiveConn->lastRecieved, receiveConn->chipId );

hudanar avatar Jan 27 '17 05:01 hudanar