Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting Static IP #863

Closed
tscrip opened this issue Jun 7, 2016 · 37 comments
Closed

Setting Static IP #863

tscrip opened this issue Jun 7, 2016 · 37 comments

Comments

@tscrip
Copy link

@tscrip tscrip commented Jun 7, 2016

I have been looking through the code, but I currently do not see a way to set a static IP. All of the comments for static IP say this feature if for future development. Is that true?

I am currently using a ESP8266 if that makes any difference.

@gfwilliams
Copy link
Member

@gfwilliams gfwilliams commented Jun 7, 2016

Just an ESP8266, or an Espruino board connected to one?

@tscrip
Copy link
Author

@tscrip tscrip commented Jun 7, 2016

Just the ESP8266. I am using the NodeMCU dev board that is based on the ESP8266.

@8eecf0d2
Copy link

@8eecf0d2 8eecf0d2 commented Jun 9, 2016

I didn't think this was possible yet?

the options should include the ability to set a static IP and associated netmask and gateway, this is a future enhancement.

http://www.espruino.com/Reference#l_Wifi_connect

@gfwilliams
Copy link
Member

@gfwilliams gfwilliams commented Jun 10, 2016

I'm not sure as I don't generally do too much ESP8266 work, but it seems like it isn't available - @tve?

You might have some luck asking on Gitter? https://gitter.im/espruino/Espruino?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge

@gfwilliams gfwilliams added the ESP8266 label Jun 10, 2016
@wilberforce
Copy link
Member

@wilberforce wilberforce commented Jun 14, 2016

@tscrip If this is in a home network you can archive the same thing by using the MAC address of the device and adding that to a dhcp reservation in your router, so it gets allocated the static address you want - still using dhcp - but getting a fixed address.

@tve tve added the enhancement label Jun 22, 2016
@tve
Copy link
Contributor

@tve tve commented Jun 22, 2016

Yup & yup. Someone "just" needs to implement the static IP piece and test it...

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jul 4, 2016

@tve something like this ?

add a function to jswrap_esp8266_network.c

/*JSON{
"type" : "staticmethod",
"class" : "Wifi",
"name" : "setIP",
"generate" : "jswrap_ESP8266_wifi_setIP",
"params" : [
["index", "JsVar", "0:STATION, 1:SOFTAP"],
["settings", "JsVar", "Configuration settings"],
["callback", "JsVar", "A function to be called back on completion."]
]
}
The settings object must contain the following properties.

  • ip IP address as string (e.g. "192.168.5.100")
  • gw The network gateway as string (e.g. "192.168.5.1")
  • netmask The interface netmask as string (e.g. "255.255.255.0")

*/
void jswrap_ESP8266_wifi_setIP(JsVar *jsIndex, JsVar *jsSettings, JsVar *jsCallback) {

....... coding ......

}

use in Espruino:

var WIFI = require("Wifi");
Wifi.setIP(0, {ip:"192.168.5.100",gw:"192.168.194.1",netmask:"255.255.255.0"}, function(e){....}); 
@gfwilliams
Copy link
Member

@gfwilliams gfwilliams commented Jul 4, 2016

IMO it'd be great to put 'index' in the setting object too (and if it's omitted and you're only in AP or Station mode, juse set the right IP automatically) - then it's the same as the other Espruino stuff

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jul 4, 2016

sure - thanks for that hint

@tve
Copy link
Contributor

@tve tve commented Jul 4, 2016

That index stuff doesn't fit into the other Wifi methods at all. Unless you want to change everything around, it should be SetIP and SetAPIP...

@gfwilliams
Copy link
Member

@gfwilliams gfwilliams commented Jul 4, 2016

it should be SetIP and SetAPIP...

Sounds good to me! I'm not sure how the index stuff ever got included - perhaps it's related to NodeMCU or EspressIf's API? Either way it's not very user-friendly :)

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jul 4, 2016

ok it is SetIP and SetAPIP - thanks for your comments.

the index stuff is Espressif API ;-)

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jul 5, 2016

@gfwilliams can you please assist, added a empty function to jswrap_esp8266_network.c and tried to compile .... got some errors I do not know how to fix.

`
//===== Wifi.setIP

/*JSON{
"type" : "staticmethod",
"class" : "Wifi",
"name" : "setIP",
"generate" : "jswrap_ESP8266_wifi_setIP",
"return" : ["JsVar", "true: Success
, false: Failure"],
"params" : [
["settings", "JsVar", "Configuration settings"],
["callback", "JsVar", "The callback to invoke when ip is set"]
]
}
The settings object must contain the following properties.

  • ip IP address as string (e.g. "192.168.5.100")
  • gw The network gateway as string (e.g. "192.168.5.1")
  • netmask The interface netmask as string (e.g. "255.255.255.0")

Return

  • true: Success

  • false: Failure

*/

JsVar *jswrap_ESP8266_wifi_setIP(JsVar *jsSettings, JsVar *jsCallback) {
return true;
}

`

make

CC /esptools/Espruino/1v85/Espruino/gen/jswrapper.o

/esptools/Espruino/1v85/Espruino/gen/jswrapper.c:952:106: error: 'jswrap_ESP8266_wifi_setIP' undeclared here (not in a function)

   {165, JSWAT_JSVAR | (JSWAT_JSVAR << (JSWAT_BITS*1)) | (JSWAT_JSVAR << (JSWAT_BITS*2)), (void (*)(void))jswrap_ESP8266_wifi_setIP},

                                                                                                          ^
/esptools/Espruino/1v85/Espruino/gen/jswrapper.c:952:3: warning: missing initializer for field 'functionPtr' of 'JswSymPtr' [-Wmissing-field-initializers]

   {165, JSWAT_JSVAR | (JSWAT_JSVAR << (JSWAT_BITS*1)) | (JSWAT_JSVAR << (JSWAT_BITS*2)), (void (*)(void))jswrap_ESP8266_wifi_setIP},

   ^
In file included from /esptools/Espruino/1v85/Espruino/gen/jswrapper.c:4:0:

/Volumes/ESPTools/Espruino/1v85/Espruino/src/jswrapper.h:73:10: note: 'functionPtr' declared here
   void (*functionPtr)(void);

          ^
@gfwilliams
Copy link
Member

@gfwilliams gfwilliams commented Jul 5, 2016

Put JsVar *jswrap_ESP8266_wifi_setIP(JsVar *jsSettings, JsVar *jsCallback) in the header file too?

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jul 5, 2016

now - thanks - miss the wood for the trees ;-)

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jul 6, 2016

ok - got three functions, first one is doing the work the other two are calling the worker.

not sure about the unlocks, call back and parameters .... please assist.

void setIP(JsVar *jsSettings, JsVar *jsCallback, int interface) {

  char ipTmp[16];
  int len = 0;

  // fist check parameter 
  if (!jsvIsObject(jsSettings)) {
    EXPECT_OPT_EXCEPTION(jsSettings);
    return;
  }

  // get,check and store ip
  JsVar *jsIP = jsvObjectGetChild(jsSettings, "ip", 0);
  if (jsIP != NULL && !jsvIsString(jsIP)) {
      EXPECT_OPT_EXCEPTION(jsIP);
      jsvUnLock(jsIP);
      return;
  }
  len = jsvGetString(jsIP, ipTmp, sizeof(ipTmp)-1);
  ipTmp[len]='\0';

  DBG(">> ip: %s\n",ipTmp);

  info.ip.addr = networkParseIPAddress(ipTmp); 
  if ( info.ip.addr  == 0) {
    jsExceptionHere(JSET_ERROR, "Not a valid IP address.");
    return;
  }

// get, check and store gw
  JsVar *jsGW = jsvObjectGetChild(jsSettings, "gw", 0);
  if (jsGW != NULL && !jsvIsString(jsGW)) {
      EXPECT_OPT_EXCEPTION(jsGW);
      jsvUnLock(jsGW);
      return;
  }
  len = jsvGetString(jsGW, ipTmp, sizeof(ipTmp)-1);
  ipTmp[len]='\0';

  DBG(">> gw: %s\n",ipTmp);

  info.gw.addr = networkParseIPAddress(ipTmp);
  if (info.gw.addr == 0) {
    jsExceptionHere(JSET_ERROR, "Not a valid Gateway address.");
    return;
  }

  // netmask setting
  JsVar *jsNM = jsvObjectGetChild(jsSettings, "netmask", 0);
  if (jsNM != NULL && !jsvIsString(jsNM)) {
      EXPECT_OPT_EXCEPTION(jsNM);
      jsvUnLock(jsNM);
      return;
  }
  len = jsvGetString(jsNM, ipTmp, sizeof(ipTmp)-1);
  ipTmp[len]='\0';

  DBG(">> netmask: %s\n",ipTmp);

  info.netmask.addr = networkParseIPAddress(ipTmp); 
  if (info.netmask.addr == 0) {
    jsExceptionHere(JSET_ERROR, "Not a valid Netmask.");
    return;
  }

  jsvUnLock(jsIP);
  jsvUnLock(jsGW);
  jsvUnLock(jsNM);

  if (interface == STATION_IF ) {
    wifi_station_dhcpc_stop();
    bool ok = wifi_set_ip_info(STATION_IF, &info);
  }
  else {
    wifi_softap_dhcps_stop();
    bool ok = wifi_set_ip_info(SOFTAP_IF, &info);
    wifi_softap_dhcps_start();
  }

  // Schedule callback

  if (jsvIsFunction(jsCallback != NULL)) {
    JsVar *jsSetIP = jsvNewObject();
    jsvObjectSetChildAndUnLock(jsSetIP, "success",jsvNewFromBool(ok));
    JsVar *params[1];
    params[0] = jsSetIP;
    jsiQueueEvents(NULL, jsCallback, params, 1); 
    jsvUnLock(params[0]);
    jsvUnLock(jsSetIP);
  }

  return;
};

//===== Wifi.setIP
/*JSON{
  "type"     : "staticmethod",
  "class"    : "Wifi",
  "name"     : "setIP",
  "generate" : "jswrap_ESP8266_wifi_setIP",
  "params"   : [
    ["settings", "JsVar", "Configuration settings"],
    ["callback", "JsVar", "The callback to invoke when ip is set"]
  ]
}

The `settings` object must contain the following properties.
* `ip` IP address as string (e.g. "192.168.5.100")
* `gw`  The network gateway as string (e.g. "192.168.5.1")
* `netmask` The interface netmask as string (e.g. "255.255.255.0")

Return 

* success : true | false
 

*/

void jswrap_ESP8266_wifi_setIP(JsVar *jsSettings, JsVar *jsCallback) {

  DBG("> Wifi.setIP\n");

  setIP(jsSettings, jsCallback, STATION_IF);

  return;
}


//===== Wifi.setAPIP
/*JSON{
  "type"     : "staticmethod",
  "class"    : "Wifi",
  "name"     : "setAPIP",
  "generate" : "jswrap_ESP8266_wifi_setAPIP",
  "params"   : [
    ["settings", "JsVar", "Configuration settings"],
    ["callback", "JsVar", "The callback to invoke when ip is set"]
  ]
}

The `settings` object must contain the following properties.
* `ip` IP address as string (e.g. "192.168.5.100")
* `gw`  The network gateway as string (e.g. "192.168.5.1")
* `netmask` The interface netmask as string (e.g. "255.255.255.0")


Return 

* success : true | false
 

*/

void jswrap_ESP8266_wifi_setAPIP(JsVar *jsSettings, JsVar *jsCallback) {

  DBG("> Wifi.setAPIP\n");

  setIP(jsSettings, jsCallback, SOFTAP_IF);

  return;
}

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jul 6, 2016

running some tests and networkParseIPAddress() returns for incomplete ip4 strings a valid result

"255.255.255" to "0.255.255.255"

"192.168.194" to "0.192.168.194"

Is this how networkParseIPAddress() should work ? checking the source code my answer is yes - hmm

Is there a more strict version of networkParseIPAddress() ?

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jul 8, 2016

@gfwilliams and @tve should Wifi.setIP look like WLAN.setIP - please assist.

@gfwilliams
Copy link
Member

@gfwilliams gfwilliams commented Jul 8, 2016

Is there a more strict version of networkParseIPAddress() ?

I don't think so - you could try and make it return a bool or something if the address wasn't correct?

should Wifi.setIP look like WLAN.setIP

I'm trying to move to using callbacks for this stuff, so what you have looks fine (especially if you don't error if there is no callback). In the case of just setting IP I guess on ESP8266 you might be able to get away without it, but on other devices you won't... and you will definitely have trouble if you go for having setIP(undefined) do DHCP like happens on other Espruino devices

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jul 8, 2016

ok - changed coding and started testing

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jul 8, 2016

@tve it is working, Wifi.getIP() shows the new value, but the ESP is not reachable on the ne IP.
What am I missing - please assist.

@wilberforce
Copy link
Member

@wilberforce wilberforce commented Jul 8, 2016

@MaBecker
Where is the code - is it here? https://github.com/MaBecker/Espruino ?

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jul 9, 2016

@tve with your hint for ping() the _setIP() and _setAPIP() is working - thanks.

@wilberforce yes - now you can find it there

@wilberforce
Copy link
Member

@wilberforce wilberforce commented Jul 11, 2016

@MaBecker

Looks good.

static struct ip_info info;

Does this need to be static or can it be allocated on the stack?

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jul 11, 2016

not sure, used the same style as ping

@wilberforce
Copy link
Member

@wilberforce wilberforce commented Jul 11, 2016

@MaBecker

not sure, used the same style as ping

Ok. The difference is that a static object is allocated space at link time, and always takes up that space.
Something allocated in function scope is allocated dynamically on the stack. This means when the function is exited, the space is given back to the system.

@wilberforce
Copy link
Member

@wilberforce wilberforce commented Jul 11, 2016

@MaBecker

Will these new settings get preserved in a Wifi.save() ?

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Aug 16, 2016

hm , I guess yes, but let me test

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Sep 4, 2016

@wilberforce: NO - the ip setting is not saved.

  1. read stored information for AP and Station
  2. starting as saved (off/sta/ap/sta+ap)
    2.1 AP open on 192.168.4.1 (ap/sta+ap)
    2.2 Station connect to saved AP and request ip by dhcp (st/sta+ap)

At the moment I have no use case where _setIP() or _setAPIP() is needed.

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Dec 12, 2016

Hi @tve can you please double check, this would be very helpful, because I am not sure about the JSON stuff and if this two function should return a boolean or not.

Next step is to create a PR for this enhancement.

  • changes to libs/network/esp8266/jswrap_esp8266_network.h

MaBecker@072dcac#diff-f388853956d7ecb9f108259d968da34a

  • changes to libs/network/esp8266/jswrap_esp8266_network.c

MaBecker@a5124aa#diff-6b36071fdae7819c38bd7144e04f3942

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jan 5, 2017

Hi @gfwilliams

added code to my fork and like to check the description /*JSON{...}... */ .

How to create the http://www.espruino.com/Reference# page ?

@gfwilliams
Copy link
Member

@gfwilliams gfwilliams commented Jan 5, 2017

Just run scripts/build_docs.py - it'll generate functions.html in the main directory

@MaBecker
Copy link
Contributor

@MaBecker MaBecker commented Jan 24, 2017

Hi @gfwilliams

how can I merge this commit into the Espruino/master ?

@gfwilliams
Copy link
Member

@gfwilliams gfwilliams commented Jan 24, 2017

Just done - if you made a branch that tracked the main Espruino repo, did git cherry-pick commit_hash, and then issues a pull request from that branch, that should have worked though

@gfwilliams
Copy link
Member

@gfwilliams gfwilliams commented Jan 24, 2017

Closing this with eabffa4

@gfwilliams gfwilliams closed this Jan 24, 2017
@trusktr
Copy link

@trusktr trusktr commented Jun 2, 2017

Can we setIP with Espruino WiFi? Seems like not. That would be nice!

@MaBecker MaBecker added the implemented label Jun 2, 2017
@gfwilliams
Copy link
Member

@gfwilliams gfwilliams commented Jun 2, 2017

This bug is the one for ESP8266 itself. Espruino WiFi doesn't do it yet, but I just filed a new one here with a workaround for it: espruino/EspruinoDocs#363

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants
You can’t perform that action at this time.