Components of lighty.io are versatile and reusable in different scenarios. Let’s take closer look at lighty-netconf-device java library. This lighty.io component represents fully programmable NETCONF communication stack, which can be integrated with hardware to achieve interoperability with lighty.io NETCONF – RESTCONF controllers. lighty-netconf-device library implements server for RFC6241 (https://tools.ietf.org/html/rfc6241) and provides related services like Datastore, RPC handling and NETCONF protocol operations (https://tools.ietf.org/html/rfc6241#section-7).

Raspberry PI is very popular platform for hardware prototyping. Raspberry PI 3 utilizes Broadcom ARMv7 BCM2835 SoC. In this example, we will build simple device equipped with 4 LED state indicators, 4 buttons and sensors for measuring temperature, relative humidity and atmospheric pressure. Device schematics and wiring is described on the picture below.

Hardware components:

– Raspberry PI 3 model B v1.2 (https://www.raspberrypi.org/products/raspberry-pi-3-model-b/)

– BMP-180 I2C Bosch temperature and atmospheric pressure sensor. (https://www.adafruit.com/product/1603)

– HTU-21D I2C temperature and relative humidity sensor. (https://www.adafruit.com/product/1899)

Software stack used on Raspberry PI device consists of following components:

– Raspbian stretch lite (https://www.raspberrypi.org/downloads/raspbian/)

– OpenJDK 8 (http://openjdk.java.net/)

– wiring pi (http://wiringpi.com/)

– pi4j (http://pi4j.com/)

– lighty.io (https://lighty.io)

Next step is to create a YANG model of the device. Model below is pretty self-explanatory:

module rpi-device {
    yang-version 1.1;
    namespace "urn:tech.pantheon.netconfdevice.rpid";
    prefix "dc";
    organization "Pantheon Technologies";
    description
        "This module represents API to Raspberry-Pi test device";
    revision "2018-02-25" {
        description
            "Initial revision";
    }
    grouping led-data {
        leaf led-id {
             type int8 {
                  range "0 .. 3";
             }
             description "Unique LED port ID. Allowed values are 0,1,2,3.";
        }
        leaf led-status {
             type boolean;
             description "LED port status true=high/on, false=low/off.";
        }
    }
    container RpiDevice {
        description "Data model of RPis test device.";
        leaf device-name {
            type string;
            description "Name of this device.";
        }
        leaf temperature {
            type decimal64 {
                 fraction-digits 3;
                 range "-200 .. 200";
            }
            config false;
            description "Ambient temperature in Celsius degree [C].";
        }
        leaf relative-humidity {
            type decimal64 {
                 fraction-digits 3;
                 range "0 .. 100";
            }
            config false;
            description "Ambient relative humidity in percentage [%].";
        }
        leaf atmospheric-pressure {
            type decimal64 {
                 fraction-digits 3;
                 range "0 .. 1000000";
            }
            config false;
            description "Atmospheric Pressure in pascals [Pa].";
        }
        list led-indicators {
             config false;
             description "0-3 LED port indicator list";
             key "led-id";
             uses led-data;
        }
    }

    rpc set-led {
        description "set LED port status high/on or low/off.";
        input {
           uses led-data;
        }
        output {
           uses led-data;
        }
    }

}

Last step is to implement Java code which initializes NETCONF stack, Datastore and hardware bindings to interact with sensors and IO ports of Raspberry PI. Example below starts NETCONF interface on port 17830. The rpi-device@2018-02-25.yang YANG model is used and the device Datastore is initialized with data from configuration. Hardware drivers for sensors and IO ports are injected using constructors. Main class, which starts NETCONF device application, looks like this:


public static void main(String[] args) {
    //1. Load models from classpath
    Set<YangModuleInfo> rpiModules = ModelUtils.getModelsFromClasspath(ModuleId.from("rpi-device", "2018-02-25"));
    //2. Initialize DataStores
    InputStream initialDataConfig = Main.class.getResourceAsStream("/initial-config.xml");
    InputStream initialDataOperational = Main.class.getResourceAsStream("/initial-operational.xml");
    //3. Initialize hardware driver
    HardwareDriver hardwareDriver = HardwareDriverFactory.create();
    //4. Initialize RPCs
    RpiDeviceServiceImpl rpiDeviceService = new RpiDeviceServiceImpl(hardwareDriver);
    SetLedProcessor setLedProcessor = new SetLedProcessor(rpiDeviceService);
    //5. Initialize Netconf device
    NetconfDevice netconfDevice = new NetconfDeviceBuilder()
            .setCredentials("admin", "admin")
            .setBindingPort(17830)
            .setInitialConfigurationData(initialDataConfig)
            .setInitialOperationalData(initialDataOperational)
            .withModels(rpiModules)
            .withDefaultRequestProcessors()
            .withRequestProcessor(setLedProcessor)
            .withDefaultCapabilities()
            .build();
    netconfDevice.start();
    //6. Initialize hardware scanner
    DataStoreService dataStoreService = new DataStoreService(netconfDevice.getNetconfDeviceServices().getDataBroker());
    hardwareDriver.setListener(dataStoreService);
    HardwareScanner hardwareScanner = new HardwareScanner(dataStoreService, hardwareDriver, TimeUnit.SECONDS, 5);
    new Thread(hardwareScanner).start();
}

Now we have NETCONF device up and running on network, let’s use lighty-netconf-restconf-app as a SDN controller to manage this device. This lighty.io based controller uses OpenDaylight core components, NETCONF south-bound plugin and Pantheon’s RESTCONF RFC8040 implementation as a north-bound plugin. Whole SDN architecture looks like this:

Now we can use RESTCONF to connect and access Raspberry PI NETCONF device in 4 easy steps:

  1. Connect the device to the SDN controller

POST https://localhost:8888/restconf/data/network-topology:network-topology/topology=topology-netconf

  {
    "netconf-topology:node" :[ {
      "node-id": "rpi-device",
      "host": "192.68.0.102",
      "port": 17830,
      "username": "admin",
      "password": "admin",
      "tcp-only": false,
      "keepalive-delay": 0,
      "netconf-node-configuration:schemaless": false
      }
    ]
  }

reply 201

reply 200:
{
    "topology": [
        {
            "topology-id": "topology-netconf",
            "node": [
                {
                    "node-id": "toaster-device",
                    "netconf-node-topology:available-capabilities": {
                        "available-capability": [
                            {
                                "capability": "urn:ietf:params:netconf:base:1.1",
                                "capability-origin": "device-advertised"
                            },
                            {
                                "capability": "urn:ietf:params:netconf:base:1.0",
                                "capability-origin": "device-advertised"
                            },
                            {
                                "capability": "urn:ietf:params:netconf:capability:candidate:1.0",
                                "capability-origin": "device-advertised"
                            },
                            {
                                "capability": "(urn:tech.pantheon.netconfdevice.rpid?revision=2018-02-25)rpi-device",
                                "capability-origin": "device-advertised"
                            }
                        ]
                    },
                    "netconf-node-topology:host": "127.0.0.1",
                    "netconf-node-topology:unavailable-capabilities": {},
                    "netconf-node-topology:connection-status": "connected",
                    "netconf-node-topology:port": 17830
                }
            ]
        }
    ]
}
reply 200
{
    "RpiDevice": {
        "atmospheric-pressure": 111111.109375,
        "device-name": "RPi device 01",
        "led-indicators": [
            {
                "led-id": 0,
                "led-status": true
            },
            {
                "led-id": 1,
                "led-status": false
            },
            {
                "led-id": 2,
                "led-status": false
            },
            {
                "led-id": 3,
                "led-status": false
            }
        ],
        "temperature": 22.2199993133544921875,
        "relative-humidity": 44.439998626708984375
    }
}
{
	"input": {
		"led-id": 0,
		"led-status": true
	}
}

reply 200:

{
    "output": {
        "led-status": true,
        "led-id": 0
    }
}

This example shows you, how easily you can create your own YANG model, to be able to manage your embedded devices with lighty.io SDN controller. If you don’t dare to write your own YANG models, you can search for opensource models from standard bodies like IETF, or Openconfig.net. If you are interested, you can Subscribe here (https://lighty.io/#contact).

Juraj Veverka

Categories: lighty.io