Coder Social home page Coder Social logo

esp-wifisettings's Introduction

WiFi configuration manager for the ESP32 and ESP8266 platforms in the Arduino framework

Screenshot of basic example Screenshot of advanced example Screenshot of everything

Description

This is a very simple, and somewhat naive, WiFi configuration manager for ESP32 and ESP8266 programs written in the Arduino framework. It will allow you to configure your WiFi network name (SSID) and password via a captive portal: the ESP becomes an access point with a web based configuration page.

It was written for ease of use, not for extended functionality. For example, restarting the microcontroller is the only way to leave the configuration portal. A button to restart is provided in the web interface.

The library generates a random password to protect the portal with, but it's only secured if you choose to do so by checking a checkbox. Of course, the user can configure pick their own password.

The configuration is stored in files in the flash filesystem of the ESP. The files are dumped in the root directory of the filesystem. Debug output (including the password to the configuration portal) is written to Serial.

Only automatic IP address assignment (DHCP) is supported.

Examples

Minimal usage

#include <SPIFFS.h>
#include <WiFiSettings.h>

void setup() {
    Serial.begin(115200);
    SPIFFS.begin(true);  // On first run, will format after failing to mount

    WiFiSettings.connect();
}

void loop() {
    ...
}

Callbacks and custom variables

void setup() {
    Serial.begin(115200);
    SPIFFS.begin(true);  // On first run, will format after failing to mount

    // Note that these examples call functions that you probably don't have.
    WiFiSettings.onSuccess  = []() { green(); };
    WiFiSettings.onFailure  = []() { red(); };
    WiFiSettings.onWaitLoop = []() { blue(); return 30; };  // delay 30 ms
    WiFiSettings.onPortalWaitLoop = []() { blink(); };

    String host = WiFiSettings.string( "server_host", "default.example.org");
    int    port = WiFiSettings.integer("server_port", 0, 65535, 443);

    WiFiSettings.connect(true, 30);
}

Other examples

  • The ArduinoOTA example shows how to enable over-the-air uploads in the WiFiSettings configuration portal. If you use the password from WiFiSettings as your OTA password, you no longer have to hard code it!

Note for ESP8266 users

The examples are written for ESP32. To use them with the older ESP8266 chip, note that in the ESP8266 world, SPIFFS is deprecated and replaced by LittleFS.

WifiSettings uses SPIFFS on ESP32, and LittleFS on ESP8266.

Simply change both occurrences of SPIFFS to LittleFS, and remove true in the call to LittleFS.begin();. LittleFS will format the filesystem by default.

Installing

Automated installation:

Getting the source for manual installation:

Reference

This library uses a singleton instance (object), WiFiSettings, and is not designed to be inherited from (subclassed), or to have multiple instances.

Functions

WiFiSettings.connect([...])

bool connect(bool portal = true, int wait_seconds = 30);

If no WiFi network is configured yet, starts the configuration portal. In other cases, it will attempt to connect to the network in station (WiFi client) mode, and wait until either a connection is established, or wait_seconds has elapsed. Returns true if connection succeeded.

By default, a failed connection (no connection established within the timeout) will cause the configuration portal to be started. Given portal = false, it will instead return false.

To wait forever until WiFi is connected, use wait_seconds = -1. In this case, the value of portal is ignored.

Calls the following callbacks:

  • WiFiSettings.onConnect
  • WiFiSettings.onWaitLoop -> int (milliseconds to wait)
  • WiFiSettings.onSuccess
  • WiFiSettings.onFailure

WiFiSettings.portal()

void portal();

Disconnects any active WiFi and turns the ESP into a captive portal with a DNS server that works on every hostname.

Normally, this function is called by .connect(). To allow reconfiguration after the initial configuration, you could call .portal() manually, for example when a button is pressed during startup.

This function never ends. A restart is required to resume normal operation.

Calls the following callbacks:

  • WiFiSettings.onPortal
  • WiFiSettings.onPortalWaitLoop
  • WiFiSettings.onPortalView
  • WiFiSettings.onUserAgent(String& ua)
  • WiFiSettings.onConfigSaved
  • WiFiSettings.onRestart

WiFiSettings.integer(...)

WiFiSettings.string(...)

WiFiSettings.checkbox(...)

int integer(String name, [long min, long max,] int init = 0, String label = name);
String string(String name, [[unsigned int min_length,] unsigned int max_length,] String init = "", String label = name);
bool checkbox(String name, bool init = false, String label = name);

Configures a custom configurable option and returns the current value. When no value (or an empty string) is configured, the value given as init is returned.

These functions should be called before calling .connect() or .portal().

The name is used as the filename in the SPIFFS, and as an HTML form element name, and must be valid in both of those contexts. Any given name should only be used once!

It is strongly suggested to include the name of a project in the name of the configuration option, if it is specific to that project. For example, an MQTT topic is probably specific to the application, while the server hostname is likely to be shared among several projects. This helps when the ESP is later reused for different applications.

Optionally, label can be specified as a descriptive text to use on the configuration portal.

Some restrictions for the values can be given. Note that these limitations are implemented on the client side, and may not be respected by browsers. For integers, a range can be specified by supplying both min and max. For strings, a maximum length can be specified as max_length. A minimum string length can be set with min_length, effectively making the field mandatory: it can no longer be left empty to get the init value.

WiFiSettings.html(...)

WiFiSettings.heading(...)

WiFiSettings.warning(...)

WiFiSettings.info(...)

void html(String tag, String contents, bool escape = true);
void heading(String contents, bool escape = true);
void warning(String contents, bool escape = true);
void info(String contents, bool escape = true);

Mix in custom text or HTML fragments, such as headings, warning texts, or info texts.

Custom HTML can be specified with the html function, which takes a tag (e.g. "p") or a tag with attributes (e.g. "p align=right") as the first argument. Only tags that take a closing tag should be used. The other functions are provided for convenience.

The contents are safely escaped by default, but raw HTML can be added by providing false as the last argument, in which case the contents are added to the page without any verification or modification. Consider the security implications of using unescaped data from external sources.

Variables

Note: because of the way this library is designed, any assignment to the member variables should be done before calling any of the functions.

WiFiSettings.hostname

String

Name to use as the hostname and SSID for the access point. By default, this is set to "esp32-" or "esp8266-", depending on the platform.

If it ends in a - character, a unique 6 digit device identifier (specifically, the hexadecimal representation of the device interface specific part of the ESP's MAC address, in reverse byte order) is added automatically. This is highly recommended.

Use only ASCII digits and letters. ASCII hyphens (-) can only be used in between other characters (i.e. not two in a row, and not as the first character). Most characters, including underscores (_) and spaces, are not valid in hostnames.

WiFiSettings.password

String

This variable is used to protect the configuration portal's softAP. When no password is explicitly assigned before the first custom configuration parameter is defined (with .string, .integer, or .checkbox), a password will be automatically generated and can be configured by the user.

It's strongly recommended to leave this variable untouched, and use the built-in password generation feature, and letting the user configure their own password, instead of "hard coding" a password.

The password has no effect unless the portal is secured; see .secure.

WiFiSettings.secure

bool

By setting this to true, before any custom configuration parameter is defined with .string, .integer, or .checkbox, secure mode will be forced, instead of the default behavior, which is to initially use an insecure softAP and to let the user decide whether to secure it.

When .secure is left in the default state, false, the user setting will be used.

When forcing secure mode, it is still recommended to leave .password unset so that a password is automatically generated, if you have a way to communicate it to the user, for example with an LCD display, or Serial.println(WiFiSettings.password);. Having hard coded password literals in source code is generally considered a bad idea, because that makes it harder to share the code with others.

WiFiSettings.language

String

The language to be used in the WiFiSettings portal. Currently supported are en and nl. Once the user has picked a language in the portal, the user setting overrides any value previously assigned. This variable is updated to reflect the currently selected language.

By default, all available languages are available. To conserve flash storage space, it is possible to select only specific languages, by specifying build flags such as LANGUAGE_EN. If only a single language is defined, this language will be used regardless of any configuration, and no language drop-down is presented to the user. Note: build flags are not available in the Arduino IDE, but can be specified in Arduino board files. In PlatformIO, build flags can be specified in the [env] section, e.g. build_flags = -DLANGUAGE_EN.

If you wish to contribute a translation, please refer to WiFiSettings_strings.h. (Note: due to storage constraints on microcontroller flash filesystems, only widely used natural languages will be included.)

WiFiSettings.on*

The callback functions are mentioned in the documentation for the respective functions that call them.

History

Note that this library was briefly named WiFiConfig, but was renamed to WiFiSettings because there was already another library called WiFiConfig.

From version 3.0.0, based on a contribution by Reinier van der Leer, this library also supports the older ESP8266, and the repository was renamed from esp32-WiFiSettings to ESP-WiFiSettings.

A note about Hyrum's Law

It is said that all observable behaviors of your system will be depended on by somebody, and you are of course free to explore the source and use any unintended feature you may find to your advantage. Bear in mind, however, that depending on any behavior that is not documented here, is more likely to cause breakage when you install a newer version of this library. The author feels no obligation to keep backwards compatibility with undocumented features :)

esp-wifisettings's People

Contributors

d-a-v avatar juerd avatar kreisverkehr avatar pwuts avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

esp-wifisettings's Issues

Compile error with expansion of macro 'F'

Whenever I try to compile this library, I get compile errors saying it cannot convert const char [] to const __FlashStringHelper* in assignment #define F(string_literal) (string_literal).

This is my Platformio.ini file:

[env:esp32thing]
platform = espressif32
board = esp32thing
framework = arduino
lib_deps =
    juerd/ESP-WiFiSettings@^3.8.0

And this is the file being compiled:
https://github.com/Juerd/ESP-WiFiSettings/blob/master/examples/Basic/Basic.ino

The errors:
image

Can anyone help me?

Wifi AP hostname

I know this library is pretty old and most likely no longer maintained but I find it to be the most versatile library among all the WiFi connection managers for ESP32.

The issue that I have is that I cannot set the AP name of ESP32 device using the WiFiSettings.hostname function. Maybe I am doing something wrong but would really appreciate if someone could guide me with an example on how to properly add hostname (AP name) definition function in my arduino sketch. Thank you!

WPS

Hi,

Please consider including WPS support.

I googled it and it doesn't look too complicated:
https://bbs.espressif.com/viewtopic.php?t=1096

The reason I'm asking: I found that "end-users" often find it problematic to enter the password for their wifi. Like casing, O versus 0, etc. and wps takes that problem supposedly away.

Having custom password fields in the AP config replace password with ***********s

Is there a way to make it so when you have a custom password input string field in the AP configuration page, like an MQTT password it ************'s out the password when a user logs into the AP Configuration page like it does the WiFi password. Or is there any easy way to add this functionality to the WiFiSettings.cpp file to have another function like WiFiSettings.passwordstring() in addition to the .string() and .integer() functions?

Make filesystem configurable

Hello!

This library uses SPIFFS as the only filesystem for ESP32. But in many sources SPIFFS marked as deprecated and it is recommended to move to LittleFS.
Now LittleFS is added to arduino-esp32 and may be preffered filesystem for many projects.

Necessary changes in WiFiSettings.cpp to work using LittleFS:

#ifdef ESP32
    #define ESPFS SPIFFS
    #define ESPMAC (Sprintf("%06" PRIx64, ESP.getEfuseMac() >> 24))
    #include <SPIFFS.h>

should be changed with:

#ifdef ESP32`
    #define ESPFS LittleFS
    #define ESPMAC (Sprintf("%06" PRIx64, ESP.getEfuseMac() >> 24))
    #include <LittleFS.h>

Using this changes everything works fine with LittleFS
Maybe filesystem type should be configurable or lib should work with both filesystems?

Feature Request: Manual SSID

Hi,

It would be great to be able to manually enter the ssid, this would allow hidden ssid's to be used.

Thanks.

WDT conflict with ESP32 support v3.x.x

Not sure if this is a problem with the library or the ESP32 support from Espressif.

When trying the minimal usage example with the esp32 package v 3.0.1 and an ESP32-C3 board, I get continuously the error

task_wdt: esp_task_wdt_reset(763): task not found

Removing the call to esp_task_wdt_reset() in WiFiSettings.cpp fixes the problem.

Trying the minimal usage example with an ESP32 DEVKIT V1 board, I always get the error, with or without the call to esp_task_wdt_reset().

ESP32 does not connect unless restarted through portal

On multiple ESP32's on multiple different Wi-Fi networks, I cannot get the device to connect to Wifi unless I hit "restart" through the portal interface. If I remove the timeout, it never connects and just fills the serial output with periods.

Warning in ESP8266

... However there's still this warning:

.../ESP-WiFiSettings/WiFiSettings.cpp: In lambda function:
.../ESP-WiFiSettings/WiFiSettings.cpp:313:40: warning: comparison is always false due to limited range of data type [-Wtype-limits]
  313 |             opt.replace("{1x}",   mode == WIFI_AUTH_WPA2_ENTERPRISE ? "(won't work: 802.1x is not supported)" : "");
      |                                        ^

which is solved by this non-invasive change:

--- a/WiFiSettings.cpp
+++ b/WiFiSettings.cpp
@@ -16,7 +16,7 @@
     #define esp_task_wdt_reset wdt_reset
     #define wifi_auth_mode_t uint8_t    // wl_enc_type
     #define WIFI_AUTH_OPEN ENC_TYPE_NONE
-    #define WIFI_AUTH_WPA2_ENTERPRISE -1337 // not available on ESP8266
+    constexpr auto WIFI_AUTH_WPA2_ENTERPRISE = -1337; // not available on ESP8266
     #define setHostname hostname
     #define INADDR_NONE IPAddress(0,0,0,0)

Originally posted by @d-a-v in #10 (comment)

Cannot connect to soft AP after .portal() is called

Hello, I'd like to be able to reconfigure some parameters on the portal even after initial configuration by having the portal brought up again after a button press. The button press function to open the portal works but for some reason, I'm not able to open the portal after successfully connecting to the soft AP. The .portal() function was called in the loop function when the button is pressed for 3 seconds. Thanks in advance for the help!

Regards,
Ameer

web interface

HI Jured,
After connecte to my router, i don't have web interface to change SSID
it is possible to make a modification in the code?
if so how can i do it
thank you

WiFiSettings.string() seems to encode the string in some way

I'm trying to get CA root certificates configured using the WiFiSettings.string(), but I keep getting the error that the certificate is invalid, while hardcoding the certificate string in code works.

Gist example:

String hardcoded_cert = "-----BEGIN CERTIFICATE-----\nMIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4XDTIxMDEyMDE5MTQwM1oXDTI0MDkzMDE4MTQwM1owTzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCt6CRz9BQ385ueK1coHIe+3LffOJCMbjzmV6B493XCov71am72AE8o295ohmxEk7axY/0UEmu/H9LqMZshftEzPLpI9d1537O4/xLxIZpLwYqGcWlKZmZsj348cL+tKSIG8+TA5oCu4kuPt5l+lAOf00eXfJlII1PoOK5PCm+DLtFJV4yAdLbaL9A4jXsDcCEbdfIwPPqPrt3aY6vrFk/CjhFLfs8L6P+1dy70sntK4EwSJQxwjQMpoOFTJOwT2e4ZvxCzSow/iaNhUd6shweU9GNx7C7ib1uYgeGJXDR5bHbvO5BieebbpJovJsXQEOEO3tkQjhb7t/eo98flAgeYjzYIlefiN5YNNnWe+w5ysR2bvAP5SQXYgd0FtCrWQemsAXaVCg/Y39W9Eh81LygXbNKYwagJZHduRze6zqxZXmidf3LWicUGQSk+WT7dJvUkyRGnWqNMQB9GoZm1pzpRboY7nn1ypxIFeFntPlF4FQsDj43QLwWyPntKHEtzBRL8xurgUBN8Q5N0s8p0544fAQjQMNRbcTa0B7rBMDBcSLeCO5imfWCKoqMpgsy6vYMEG6KDA0Gh1gXxG8K28Kh8hjtGqEgqiNx2mna/H2qlPRmP6zjzZN7IKw0KKP/32+IVQtQi0Cdd4Xn+GOdwiK1O5tmLOsbdJ1Fu/7xk9TNDTwIDAQABo4IBRjCCAUIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwSwYIKwYBBQUHAQEEPzA9MDsGCCsGAQUFBzAChi9odHRwOi8vYXBwcy5pZGVudHJ1c3QuY29tL3Jvb3RzL2RzdHJvb3RjYXgzLnA3YzAfBgNVHSMEGDAWgBTEp7Gkeyxx+tvhS5B1/8QVYIWJEDBUBgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIBFiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuaWRlbnRydXN0LmNvbS9EU1RST09UQ0FYM0NSTC5jcmwwHQYDVR0OBBYEFHm0WeZ7tuXkAXOACIjIGlj26ZtuMA0GCSqGSIb3DQEBCwUAA4IBAQAKcwBslm7/DlLQrt2M51oGrS+o44+/yQoDFVDC5WxCu2+b9LRPwkSICHXM6webFGJueN7sJ7o5XPWioW5WlHAQU7G75K/QosMrAdSW9MUgNTP52GE24HGNtLi1qoJFlcDyqSMo59ahy2cI2qBDLKobkx/J3vWraV0T9VuGWCLKTVXkcGdtwlfFRjlBz4pYg1htmf5X6DYO8A4jqv2Il9DjXA6USbW1FzXSLr9Ohe8Y4IWS6wY7bCkjCWDcRQJMEhg76fsO3txE+FiYruq9RUWhiF1myv4Q6W+CyBFCDfvp7OOGAN6dEOM4+qR9sdjoSYKEBpsr6GtPAQw4dy753ec5\n-----END CERTIFICATE-----\n";

void setup() {
    /*
        Setup WiFiSettings
    */

    // Set the value of this string the same as the hardcoded_cert
    String rest_cert = WiFiSettings.string("rest_cert", 2000, "", T.config_rest_cert);
    // Noticed that `\`s gets escaped
    rest_cert.replace("\\n", "\n");

    WiFiClientSecure wificlient;

    // The one from the settings does not work
    wificlient.setCACert(rest_cert.c_str());

    // The hardcoded cert works
    wificlient.setCACert(hardcoded_cert.c_str());

    /*
        Begin and wait for WiFi Connection
    */

    // Will error with the rest_cert configured
    wificlient.connect("webscripts-io.waylay.io", 443)
}

I see in the library that the setting values get stored to disk, is it possible that this step encodes the string in some way? Maybe I'm missing something obvious.

MQTT client, PubSubClient

Hi Jeud,

Is PubSubClient compatible with ESP-WiFiSettings? If so, could you perhaps share a very basic example?

SSID with apostrophe is truncated

Using version 3.3.0 of the library on an ESP-WROOM-32 board, specifically the AWS ESP32 Lanyard, the SSID is being truncated at an apostrophe character.

Steps to reproduce:
code:

#include <WiFiSettings.h>

void setup() {
  Serial.begin(115200);
  SPIFFS.begin(true);  // On first run, will format after failing to mount

  WiFiSettings.connect();

}

void loop() {
  Serial.println("Hello World");
  delay(2000);
}
  1. Start up device.
  2. Connect to configuration network
  3. Select the desired SSID: House Bettis's Wi-Fi Network
  4. Enter the proper password
  5. Click Save
  6. Get an error that House Bettis is not in range

Compilation error with platform espressif8266 version 3.1.0

Hello!
After updating espressif8266 platform to the latest version 3.1.0 can't compile my sketch. I have error, located in ESP-WiFiSettings\WiFiSettings.cpp file.
The error output:

.pio\libdeps\d1_mini_E22-400M30S\ESP-WiFiSettings\WiFiSettings.cpp: In member function 'void WiFiSettingsClass::begin()'
:
.pio\libdeps\d1_mini_E22-400M30S\ESP-WiFiSettings\WiFiSettings.cpp:11:35: error: expected ')' before '__INT32'
11 | #define ESPMAC (Sprintf("%06" PRIx32, ESP.getChipId()))
| ^~~~~~

Environment:
- wemos d1 mini
- CLion + platformio
- platform espressif8266 version 3.1.0

Drop down list on custom variables

Hi,
This is not really an issue but a request for help.
The library works fine, it is simple and as a good looking interface. I use custom variables with success.
However I need a variable that must be on drop down list (use must choose from one of 20 or more values) on the portal.
This will be similar to the one that appears when we choose the SSID.
It is any way to implement it? I have tried with HTML but without success.
I don' have the skills to modify the library..

Thanks in advance for any help.

Joaquim

Didn't work with ESP32 C3 version

Hi,

I just try advanced and OTA version form your sample.
I did compile and run
Serial give me AP and SSID ESP-xxxxx and a password
But this device is not really on air ????

Getting 255.255.255.255 as IP address

Hi,

I came across your useful library and started testing it. Getting the portal and doing what is need is fine however when WiFi network is configured I saw 2 things

First after succesfull config followed by a reboot, connection to my WiFi network failed. Doublechecked pw and that's not the issue.

19:28:53.054 -> Connecting to WiFi SSID Engrie.............................. failed.
19:29:10.139 -> Starting access point for configuration portal

But, this one might not be related to your lib as I have it with the normal WiFi library as well where I need a second reboot to get connected.
However the second reboot gives me an IP (I guess) of 255.255.255.255.

19:29:18.989 -> Connecting to WiFi SSID Engrie.255.255.255.255

I came across that one some weeks ago after upgrading to the new core. The solution was simple but re-create a previous issue. See my comments in one of my apps written

// Next line was needed before Core 1.0.5 to set the hostname correctly
// since Core 1.0.5 rc6 no longer. see espressif/arduino-esp32#4732
// leaving the line will result in getting 255.255.255.255 as IP-address.
// WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
// removing line above curres getting ip 255.255.255.255 but
// brings back the issue of hostname not being set in DHCP - DAMMED!!!!
WiFi.mode(WIFI_STA);
WiFi.setHostname(hostname);
WiFi.begin(wifiSSID, wifiPassword, WIFI_ALL_CHANNEL_SCAN);

Is this related or do I have another problem?
NB: The issue I had was I could not get the hostname in my DHCP. with previous core(s) adding the line WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE); curred that one.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.