ESP8266 Sming – How to start

After dumping Lua Nodemcu for doing any useful work/tinkering on the ESP8266(it works fine for simple things and that’s it), from the available options for programming the ESP8266, native C/C++ SDK programming, Arduino, Sming, Smart.js and Espruino, I’ve selected Sming. One of the main reasons for selecting Sming is the huge range of working examples comprising HTTP clients, servers, AJAX, sensors, MQTT, you name it. Also I can use Netbeans IDE to build the ESP8266 applications and since Netbeans offers code completion, It can help a lot with the apparent lack of API documentation.

Netbeans Sming Code Compltetion

Netbeans Sming Code Compltetion

Another advantage that is not stated enough is the SPIFFS file system support. Install spiffy and under your project directory, create a files sub-directory, put the files there, and those files are flashed onto the ESP8266 as the SPIFFS file system…

How to start
Install first the esp-open-sdk and then Sming. The Sming instructions are pretty clear, in my opinion, on the GitHub site. Also if using Netbeans instructions are here: Setting up Sming with Netbeans. Make sure that the include paths are configured. It will enable code completion and get rid of the “errors” on the IDE.

After that we can export the variables ESP_HOME and SMING_HOME with the esp-open-sdk and Sming paths, or change the Makefile-user.mk of each project to point to the correct locations.

Installing and configuring Spiffy.

The following instructions are deprecated! -> See below how to install from SmingHub.
As usual, download spiffy from Github, compile, and make Sming aware of its location:

[pcortex@dune:opt]$ git clone https://github.com/alonewolfx2/spiffy
Cloning into 'spiffy'...
remote: Counting objects: 101, done.
remote: Total 101 (delta 0), reused 0 (delta 0), pack-reused 101
Receiving objects: 100% (101/101), 78.41 KiB | 0 bytes/s, done.
Resolving deltas: 100% (54/54), done.
Checking connectivity... done.
[pcortex@dune:opt] cd spiffy
[pcortex@dune:spiffy master]$ mkdir build
mkdir: created directory ‘build’
[pcortex@dune:spiffy master]$ make

Under the directory build should be now a binary named spiffs.

Goto now to the Sming/Sming subdirectory and edit the Makefile-project.mk and edit the SPIFFY ?= spiffy line to include the full path of spiffy. In my case:

# Full path spiffy command, if not in path.
SPIFFY ?= /opt/spiffy/build/spiffy

With this change when we clone one of the available projects we can just create a files subdirectory under the project directory to enable files that are put there to be flashed onto the ESP8266. Just make sure that you add to the project Makefile-user.mk file the line: SPIFF_FILES = files

Spiffy from SmingHub

The latest version of Sming that is available from Sming Hub already has spiffy available. We just need to build it.

[pcortex@dune:opt] cd /opt/Sming/Sming/spiffy
[pcortex@dune:spiffy] make

And that’s it, spiffy binary is now available.
Another way to build is just to make spiffy at the /opt/Sming/Sming directory.

First project
For first project I recommend to clone/copy one of the provided examples to a directory OUT of the Sming folders. Why? Because in this case we won’t have any conflicts when doing a git pull to update the Sming framework, and we keep the original projects intact, so we can use them as reference.

After copying the project we can see that the file structure is simple, and coding isn’t that hard ( but it’s needed to have some C and C++ proficiency ) to build applications. Coding on Sming framework is very similar to programming for an Arduino function and library wise, but with some differences, namely the callback “way” of programming and the nonexistence of the setup()/loop() paradigm (it doesn’t makes sense on a callback way of programming).

The code folder structure should mimic the example projects, namely a root folder where the make files reside, and under this folder the app folder for application files (.cpp, .c), the include folder for include files, and a files folder (optional) for holding files for the spiff file system.
Still these folders can be changed by modifying the Makefile-user.mk file at the root directory, namely the MODULES entry and the SPIFF_FILES entry:

Makefile-user-mk:
#Add your source directories here separated by space
# Sources under the ./app and ./libcode1 and ./libcode2
MODULES = app libcode1 libcode2

## MacOS / Linux:
ESP_HOME = /opt/esp-open-sdk

# MacOS / Linux
SMING_HOME = /opt/Sming/Sming

# MacOS / Linux:
# COM_PORT = /dev/ttyUSB0

# Com port speed
COM_SPEED	= 115200

# SPIFFs files Location
SPIFF_FILES = web

Programming

All Sming framework based programs must provide a init() function, that is called at ESP8266 startup. There is no setup() or loop() functions. The later function doesn’t make sense since for programming the ESP8266 we register a function for an event, and that function is called when the event triggers. No need for pooling and/or looping. So no loop() function. The Arduino sketch setup() function is in our Sming framework our init() function…

On the init() function we can setup a lot of things like, pin modes, serial port, and of course Wifi connectivity. Programming with an IDE that offers code completion allows us to see the available API and guess some of the functionality even without documentation ( note that most of the API is identical/similar to the Arduino).

So for programming with the Sming framework these are some of my notes that might be helpful:

Serial port
The always helpful serial port… allows the output of data and debugging information and keyboard input, at least when the device is connected to the computer.
The serial port usage from a coding stand point is identical to the Arduino library, but ESP8266 outputs some debugging information also for the serial port:

Serial.systemDebugOutput( flag ) - Enables/disables framework debugging.

When the value of the input parameter flag is true, we can see a lot of information, including HTTP headers, and so on. Quite verbose, which means that our output might be lost in the middle of this debugging information.
Still with the above flag set as false we can still see some debug output that can be almost completely shut off with the following instruction: system_set_os_print(0);.

So a standard init function would be something like:

void init() {
        system_set_os_print(0);  // Zero to disable, 1 to enable. Disable SDK output to serial 
  	Serial.begin(SERIAL_BAUD_RATE); // 115200 by default. SERIAL_BAUD_RATE constant is defined in include/user_config.h
	Serial.systemDebugOutput(false); // Disable debug output to serial
   
        Serial.println("Starting up!...");
        //....

}

A final note regarding printing to the serial port and debugging, we can use the higher level Serial output instructions, but with Sming we also can use/mix the standard SDK instructions: this means that we can also use the functions debugf and os_printf.

System ready
We can on the init function register a callback for when the system is ready:

void systemIsReady() {
   // do stuff.
   // Start servers
   // Note that wifi connection here is not assured. 

}

void init() {
        system_set_os_print(0);  // Zero to disable, 1 to enable. Disable SDK output to serial
  	Serial.begin(SERIAL_BAUD_RATE); // 115200 by default. SERIAL_BAUD_RATE constant is defined in include/user_config.h
	Serial.systemDebugOutput(false); // Disable SMING debug output to serial
   
        Serial.println("Starting up!...");
        //....

        System.onReady(systemIsReady);
}

Wifi Connection
Almost all the examples have the setting up of a wifi connection, some as a client, others as access point.
The important thing is that the all the callback functionality either on success or failure is already implemented, and so it’s quite easy to check for success or failure.

// Will be called when WiFi station was connected to AP
void connectOk()
{
        String devIP;
        String mac;
	Serial.println("I'm CONNECTED");

        devIP = WifiStation.getIP().toString();
        
        Serial.println("Device IP : " + devIP );

        mac = WifiStation.getMAC();
        mac.toUpperCase();
        Serial.println("Mac addrs: " + mac );
        ...
}

// Will be called when WiFi station timeout was reached
void connectFail()
{
	Serial.println("I'm NOT CONNECTED. Need help :(");

        WifiStation.waitConnection(connectOk, 20, connectFail); // We recommend 20+ seconds for connection timeout at start
}

void init() {

    // ....
	WifiStation.config(WIFI_SSID, WIFI_PWD);
	WifiStation.enable(true);
	WifiAccessPoint.enable(false);

	// Run our method when station was connected to AP (or not connected)
	WifiStation.waitConnection(connectOk, 20, connectFail); // We recommend 20+ seconds for connection timeout at start

    //....

}

Note that is way easier than Nodemcu Lua where we need to implement the connection check by ourselfs by doing a timer based pooling.
With Sming is quite easy, connectOK() is called when a successful connection is made, and connectFail() is called if the timeout (the second parameter) is reached and a connection isn’t made.

On connectFail() we can just again repeat the same instruction or list the available networks and try to connect to some of them.

Still, in my opinion, we should set up the WIFI parameters and connection initiation under the system ready callback.

Some code snippets
List the available wifi networks:

// callback function for WifiStation.startScan(networkScanCompleted);
void networkScanCompleted(bool succeeded, BssList list)
{

	if (!succeeded)
	{
		Serial.println("Failed to scan networks");
		return;
	}

	for (int i = 0; i < list.count(); i++)
	{
		Serial.print("\tWiFi: ");
		Serial.print(list[i].ssid);
		Serial.print(", ");
		Serial.print(list[i].getAuthorizationMethodName());
		if (list[i].hidden) Serial.print(" (hidden)");
		Serial.println();
	}
}

void init() {
    //...
    WifiStation.startScan(networkScanCompleted);
    //...
}

List system info.

void ShowInfo() {
    Serial.printf("\r\nSDK: v%s\r\n", system_get_sdk_version());
    Serial.printf("Free Heap: %d\r\n", system_get_free_heap_size());
    Serial.printf("CPU Frequency: %d MHz\r\n", system_get_cpu_freq());
    Serial.printf("System Chip ID: 0x%x\r\n", system_get_chip_id());
    Serial.printf("SPI Flash ID: 0x%x\r\n", spi_flash_get_id());
    Serial.printf("SPI Flash Size: %d\r\n", (1 <> 16) & 0xff)));
}

The above snippet was kind of important because it shows how to get the system or chip id that can used to identify the device, for example, in MQTT device names.

Just a final note, that all the above code and snippets are collected from several sources:

– Sming Examples
– ESP8266.Com forum
– GitHub: https://github.com/dmarkey/smarthome_esp8266RCcontroller_sming.git and mainly https://github.com/gernoteger/DobbyESP

Advertisements

Android SDK and NetBeans

I’m user of Netbeans for my Java related work.

The Android SDK instructions refer the use of Eclipse as the IDE of choice, but is also possible to use Netbeans with the NBAndroid plugin, available at http://www.nbandroid.org/

Just following the instructions for installing the plugin in into Netbeans, namely by adding the plugin URL and installing them.

One issue that I’ve found was that the New Project Wizard didn’t show the Android type applications for creation…

For making on the New Project Wizard the Android Projects available to be created, you must enable the JAVA ME plugin, so just go again to Plugins and select JAVA ME and press Enable at the bottom of the window.

It should work now.

 

[K]Ubuntu and Netbeans 6.1 with Firefox 3.0

One annoying things that took some time to solve was that on the Start page of Netbeans there are URL’s to several articles, blog posts and so one, but every time I’ve pressed one of the it say’s that it could not execute Firefox.

I’ve checked the path, permissions, and so on but with no solution.

Well the issue is quite simple:

Goto Netbeans Tools menu and select the last option Options. It should start on the general tab where you select the browser you which to use.

Select Edit and on the arguments for Firefox remove whats there: -remote “openURL({URL})” and just keep the {URL} nothing else.

Save, close and it should work.

Now back to work…