Micurest

Micurest © GPL3+

μcuREST is a C++11 library for implementing REST services on constrained platforms, such as bare metal applications on low-end MCUs.

  • 423 views
  • 1 comment
  • 4 respects

Components and supplies

About this project

Introduction

μcuREST (micurest) is a C++11 library for implementing REST services on constrained platforms, such as bare metal applications on low-end MCUs. The library is platform-agnostic, zero-allocation, and has almost no external dependencies. It allows mapping hierarchically organized URIs to C/C++ variables, constants and methods, and exposing the URIs via HTTP protocol.

Architecture

Diagram on the left shows architecture of a RESTful application, implemented with μcuREST library. The latter facilitates the Core, a set of Content Providers and a set of Resource Mapping Templates. For some platforms, μcuREST also provide implementation of I/O stream interfaces to platform specific Transport Layer. The Application provides content (variables, functions, methods) and a Resource Map, which is the key part of application’s design. This map statically (at compile time) associates application content with URIs and content providers.

Transport Layer

An application, implementing HTTP RESTful services with μcuREST, needs a platform specific transport layer and a mediator (Session Layer in terms of OSI model) between μcuREST and the transport layer. The mediator must handle sessions and implement two interfaces: istream and ostream.

Resource Map

Resource map is defined with C++ language, using a set of templates. Example of a simple map is given on Example 1, a more complicated example available on Example 2.

/* map of URIs to application resources */
const directory& resourceMap() noexcept {
  return Root<
    resource::FileConstString<name::hello_html, hello_html_content, media::html>,
    resource::FileText<name::hello, sizeof(hello_text), hello_text>,
    resource::FileFunctions<name::led, bool, getLed, setLed>
  >();  
}
/* map of URIs to application resources
 * D defines a directory,
 * E defines an entry with a name and content node
 * N defines a content node
 * F combines E and N in one for simple content, such as variables
 */
const directory& resourceMap() noexcept {
	return Root<		/// this notation documents URI of the resource
		/*		cost of adding another page: 190/28							*/
		/* first entry that matches accepted content is served by default	*/
		E<name::io,   Embed<io>>,
		/* directory d	 													*/
		D<name::d,
			E<name::X,
				N<V<micurest::accessor::vector<byte,
					digital_read, digital_write, digital_has>>>>,
			E<identity::numeric,
				N<micurest::accessor::vector<byte,
					digital_read, digital_write, digital_has>>>>,
		/* directory r	 													*/
		D<name::r,
			E<name::X,
				N<V<micurest::accessor::vector<byte,
					relay_read, relay_write, relay_has>>>>,
			E<identity::numeric,
				N<micurest::accessor::vector<byte,
					relay_read, relay_write, relay_has>>>>,
		/* directory a	 													*/
		D<name::a,
			E<name::X,
				N<V<micurest::accessor::bunch<int,
					analog_read, analog_has>>>>,
			E<identity::numeric,
				N<micurest::accessor::bunch<int,
					analog_read, analog_has>>>>,
		/* directory in	 													*/
		D<name::in,
			E<name::X,
				N<V<micurest::accessor::bunch<byte,
					interrupt_read, interrupt_has>>>>,
			E<identity::numeric,
				N<micurest::accessor::bunch<byte,
					interrupt_read, interrupt_has>>>>,
		E<name::X, json_node>,
		F<name::blob,&blob_length, sizeof(blob), blob>,
		F<name::mode, pointer<enums::mode_t, &mode>>,
		E<name::modes,
			N<enums::list<enums::mode_names>>>,
		E<name::ip, N<V<ip_addr, &ip>>>,
		E<name::mac, N<V<mac_addr, &mac>>>,
		E<name::rtc, Object<datetime>>,
		E<name::demo, Embed<demo>>,
		F<name::natural, pointer<unsigned, &natural>>,
		F<name::logical, pointer<bool, &logical>>,
		F<name::text, countof(text), text>
	>();
}

Limitations

μcuREST implements a minimal subset of HTTP specification, sufficient for serving GET requests from browsers, GET/PUT/POST requests from JavaScript via XMLHttpRequest and simple machine-to-machine communications. Only normalized case-sensitive URIs are supported. Query strings, cookies, absolute URLs, cache control, transfer encoding, and many other HTTP features are not supported. Support for authentication is currently in consideration.

Depending on the transport layer in use and the mediator implementation, HTTM message size could be limited to the size of one MTU (~1460 bytes).

Principle of Operation

  • When a client sends an HTTP requests, the Transport Layer receives it and makes the data available to the application.
  • The Session Layer detects presence of the data, creates I/O streams to interface the data, and calls μcuREST for servicing the request.
  • μcuREST starts parsing the HTTP header and, as it progresses with URI, calls resource map for finding a Content Provider matching the URI.
  • When the HTTP header is parsed, μcuREST calls the matched Content Provider to process message body (if such is available).
  • The Content Provider reads message body, parses it in its specific way and delivers content to the associated application’s variable or function.
  • If parsing and content delivery finishes with success, μcuREST starts writing success HTTP response and calls the Content Provider to write message body.
  • The Content Provider obtains content from the application’s variable or function, formats the data in its specific way and writes the message body. When message servicing complete the Session Layer finishes the session and closes connection (unless keep-alive is present in the header and supported by the Transport Layer)

Requirements

  • Compiler: μcuREST sources need a C++11 enabled compiler, such as g++-4.8 and up.
  • Library: libstdc++ v3 highly desirable. But if not available a workaround exists
  • Transport layer: A platform specific transport layer, such as TCP/IP, is required for implementing HTTP REST services.
  • ROM/RAM space: on AVR platform μcuREST core takes 6K of ROM and 100 bytes of RAM. Size of the resource map starts with 3K/200 and grows with its complexity, taking in average 750 bytes of ROM and 250 bytes of RAM per entry.

Screenshots

Below you may find screenshots of web pages, implemented in examples for Controllino MAXI and ESP8266 NodeMCU:

Code

Comments

Similar projects you might like

Embedis: Project Keystore Library

by thingSoC

  • 1,711 views
  • 1 comment
  • 8 respects

Race Car Dashboard (Online Connectivity)

Project showcase by Team Jatayu

  • 15,300 views
  • 48 comments
  • 31 respects

SerialDebug: Improving Debug to Arduino

Project tutorial by JoaoLopesF

  • 2,970 views
  • 6 comments
  • 27 respects

IoT Button That Controls Your App

Project tutorial by AppShed Support

  • 2,463 views
  • 2 comments
  • 7 respects

IoT Blink - Getting started with IoT

Project showcase by AppShed Support

  • 2,259 views
  • 1 comment
  • 13 respects

How To Use TheAmplituhedron.com To Improve IoT Projects

Project tutorial by Kutluhan Aktar

  • 1,307 views
  • 0 comments
  • 9 respects
Add projectSign up / Login