Skip to content

Weather RPC

This tutorial explains how to create and expose dataBridges RPC functions. dataBridges RPC provide reliable two-way messaging between multiple endpoints allowing you to build sophisticated asynchronous interactions take a look at RPC details at Detailed API documentation.

In this tutorial, we wil be exposing RPC Server weather.now and a function called currentWeather. The function weather.now(currentWeather) will give you a summary weather info for the location you pass it as parameter.

For example weather.now(currentWeather["Mumbai"]) will return back weather summary

Weather Condition : Smoke
Temprature : 29.99°C, feels like 29.16°C, humidity : 35
Pressure : 29.99 hPa , Visibility : 3000 meter, Cloudiness : 0 %
Wind : Speed 2.06 meter/sec , Wind direction : 290 °
Sunrise : 6:38:43 AM, Sunset : 6:05:33 PM
This tutorial uses https://openweathermap.org/ to get weather details. You need to register at https://openweathermap.org/ and get an API AppID from openweathermap.org. We will be using this openweathermap.org API to fetch weather information.

You will also understand how dataBridges language bindings allows you to consume these API's in local language implementation which greatly simplifies new app development and rollouts.

Project Source

Download source

Download the rpc.weather.client by clicking on this link

Download the rpc.weather.server by clicking on this link

Download source

Download the rpc.weather.client by clicking on this link

Download the rpc.weather.server by clicking on this link

Download source

Download the rpc.weather.client by clicking on this link

Download the rpc.weather.server by clicking on this link

Dependencies

Dependencies

For this application, you will require to use moment,node-fetch,databridges-sio-client-lib (dataBridges Client Library) and databridges-sio-server-lib (dataBridges Server Library) with NodeJS.

  • Install External dependencies
  • npm install moment node-fetch --save

  • Install dataBridges library

  • npm install databridges-sio-client-lib databridges-sio-server-lib --save

Download the package.json by clicking on this link

We will be using api.openweathermap.org for fetching realtime weather information.

Dependencies

For this application, you will require to use aiohttp,asyncio,certifi,databridges-sio-client-lib (dataBridges Client Library) and databridges-sio-server-lib (dataBridges Server Library).

  • Install External dependencies
  • pip3 install aiohttp
  • pip3 install asyncio
  • pip3 install certifi

  • Install dataBridges library

  • pip3 install databridges_sio_client_lib
  • pip3 install databridges_sio_server_lib

We will be using api.openweathermap.org for fetching realtime weather information.

Dependencies

For this application, you will require to use Databridges.Sio.Client.Lib (dataBridges Client Library) and Databridges.Sio.Server.Lib (dataBridges Server Library).

  • Install dataBridges library from "Manage NuGet Packages..." from the Solution -> Application Name context menu.

Set up a dataBridges account and app

Before we jump right into setting up an application with dataBridges, you’ll need to create a dataBridges account and app, if you don’t already have one:

  1. Sign up for a dataBridges account.

  2. Create a new app by selecting Apps and clicking Create New button.

  3. You can retrieve your app credentials from the App Keys tab.

Major Components of this example

Lets first understand how this example is structured.

This example has two files one is for running the RPC server, other is for testing the RPC server using dataBridges client library.

  • rpc.weather.server
  • rpc.weather.client

rpc.weather.server serves weather.now RPC server which has currentWeather function exposing functionality search weather information of keyword from openweathermap.org. This function can be called by RPC client using RPC call functionlity.

// Initialize RPC Server weather.now.
let weathersvr = dbridge.rpc.init("weather.now");

// Define  exposed functions.
function currentWeather(payload, response) {
    const startTime = moment().valueOf();
    // Using openweathermap.org api to fetch realtime weather data.
    const weatherURI = 'https://api.openweathermap.org/data/2.5/weather?q=' + payload.inparam + '&appid=' + weather_APPID + '&units=metric'; 
    let fetchRes = fetch(weatherURI);
    fetchRes.then((retResponse) => {
        if (!retResponse.ok) {
            throw new Error('Network response was not OK');
        }
        return retResponse.json();
    }).then(async (resp) => {
        let responseData = 'Weather Condition : ' + resp.weather[0].main + '\n'
        responseData = responseData + 'Temperature : ' + resp.main.temp + '\u00b0C, feels like ' + resp.main.feels_like + '\u00b0C, humidity : ' + resp.main.humidity + '\n'
        responseData = responseData + 'Pressure : ' + resp.main.temp + ' hPa , Visibility : ' + resp.visibility + ' meter, Cloudiness : ' + resp.clouds.all + ' %' + '\n'
        responseData = responseData + 'Wind : Speed ' + resp.wind.speed + ' meter/sec , Wind direction : ' + resp.wind.deg + ' \u00b0' + '\n'
        responseData = responseData + 'Sunrise : ' + moment.unix(resp.sys.sunrise).format('h:mm:ss A') + ', Sunset : ' + moment.unix(resp.sys.sunset).format('h:mm:ss A') + '\n'
        response.end(JSON.stringify({
            statuscode: 0,
            exectime: moment().valueOf() - startTime,
            data: responseData
        }));
    }).catch((err) => {
        console.log('Error in fetching weather details', err);
        response.end(JSON.stringify({
            statuscode: 1,
            exectime: moment().valueOf() - startTime,
            data: 'openweathermap.org api exception..' + err.source + ',' + err.code + ',' + err.message
        }));
    });
}

// Define all exposed functions.
weathersvr.functions = function () {
    weathersvr.regfn("currentWeather", currentWeather);
}

// Bind to server.registration.success, This will be triggered When weathersvr is ready to serve.
weathersvr.bind("dbridges:rpc.server.registration.success", (payload, metadata) => {
    console.log(moment().format('h:mm:ss:ms'), "dbridges:rpc.server.registration.success");
});
// Bind to server.registration.fail, This will be triggered When any registration issue is raised.
weathersvr.bind("dbridges:rpc.server.registration.fail", (payload, metadata) => {
    console.log(moment().format('h:mm:ss:ms'),"dbridges:rpc.server.registration.fail");
});

// Bind to server.online, This will be triggered When MathServer is ready to serve.
weathersvr.bind("dbridges:rpc.server.online", (payload, metadata) => {
    console.log(moment().format('h:mm:ss:ms'), "dbridges:rpc.server.online");
});

// Register RPC Server with dBrdige network.
weathersvr.register();
# Define all exposed functions.
async def rpc_expose_functions(self):

    async def currentWeather(inparameter, response):
        #  Enable this to receive response tracker event.
        payload = inparameter["inparam"]
        weatherURI = 'https://api.openweathermap.org/data/2.5/weather?q=' + payload + '&appid=' + self.weatherAPPId + '&units=metric';

        try:
            ssl_context = ssl.create_default_context(cafile=certifi.where())
            async with aiohttp.ClientSession() as session:
                async with session.get(weatherURI, ssl=ssl_context) as r:
                    if r.status != 200:
                        jsonobject = {"statuscode": 1,"exectime": (time.time() - start_time), "data": ""}
                        await response.end(json.dumps(jsonobject))
                    if r.status == 200:
                        rdata = await r.text()
                        resp = json.loads(rdata)
                        responseData = "Weather Condition : " + str(resp["weather"][0]["main"]) + "\n"
                        responseData = responseData + "Temperature : " + str(resp["main"]["temp"]) + "\u00b0C, feels like " + str(resp["main"]["feels_like"]) + "\u00b0C, humidity : " + str(resp["main"]["humidity"] )+ "\n"
                        responseData = responseData + "Pressure : " + str(resp["main"]["temp"]) + " hPa , Visibility : " + str(resp["visibility"]) + " meter, Cloudiness : " + str(resp["clouds"]["all"]) + " %" + "\n"
                        responseData = responseData + "Wind : Speed " + str(resp["wind"]["speed"]) + " meter/sec , Wind direction : " + str(resp["wind"]["deg"] )+ " \u00b0" + "\n"
                        responseData = responseData + "Sunrise : " + str(resp["sys"]["sunrise"])+ ", Sunset : " + str(resp["sys"]["sunset"] )+ "\n"
                        jsonobject = {"statuscode": 0,
                        "exectime": (time.time() - start_time),
                        "data": responseData }
                        await response.end(json.dumps(jsonobject))
        except Exception as e:
            jsonobject = {"statuscode": 1,"exectime": (time.time() - start_time), "data": ""}
            await response.end(json.dumps(jsonobject))

    try:
        #  Bind the exposed function, so that library can register it for receiving calls.
        self.rpcServer.regfn("currentWeather", currentWeather)
    except dBError as dberror:
        print("Exception: ", dberror.source, dberror.code, dberror.message)


# Initialize RPC Server weather.now1.
self.rpcServer = self.dbridge.rpc.init("weather.now")
self.rpcServer.functions = self.rpc_expose_functions

try:
    #  Register RPC Server with dBrdige network.
    await self.rpcServer.register()
except dBError as dberror:
    #  Catch any registration error.
    print("Exception: ", dberror.source, dberror.code, dberror.message)
// Define exposed functions.
// RPC: the client sends a single request and receives a single response.
public async void currentWeather(object inparameter, object response)
{
    dBridges.Utils.dBParams parameter = inparameter as dBridges.Utils.dBParams;
    dBridges.responseHandler.CResponseHandler responsehandler = response as dBridges.responseHandler.CResponseHandler;

    using (var client = new HttpClient()) {
        try {
            ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;
            string payload = parameter.inparama;
            var watch = new System.Diagnostics.Stopwatch();
            string url = "https://api.openweathermap.org/data/2.5/weather?q=" + payload + "&appid=" + this.weatherAPPId + "&units=metric";
            var responsedata = await client.GetAsync(new Uri(url));

            if (!responsedata.IsSuccessStatusCode) {
                Dictionary<string, object> resultjson = new Dictionary<string, object>();
                resultjson.Add("statuscode", 1);
                watch.Stop();
                resultjson.Add("data", responsedata.ReasonPhrase);
                resultjson.Add("exectime", watch.ElapsedMilliseconds);
                jsonstring = JsonConvert.SerializeObject(resultjson);
                await responsehandler.end(jsonstring);
            } else {
                string jsonstring = await responsedata.Content.ReadAsStringAsync();
                dynamic resp = JsonConvert.DeserializeObject(jsonstring);
                string responseData = "Weather Condition : " + resp["weather"][0]["main"] + "\n";
                responseData = responseData + "Temperature : " + resp["main"]["temp"] + "\u00b0C, feels like " + resp["main"]["feels_like"] + "\u00b0C, humidity : " + resp["main"]["humidity"] + "\n";
                responseData = responseData + "Pressure : " + (resp["main"]["temp"]) + " hPa , Visibility : " + (resp["visibility"]) + " meter, Cloudiness : " + (resp["clouds"]["all"]) + " %" + "\n";
                responseData = responseData + "Wind : Speed " + (resp["wind"]["speed"]) + " meter/sec , Wind direction : " + (resp["wind"]["deg"]) + " \u00b0" + "\n";
                responseData = responseData + "Sunrise : " + (resp["sys"]["sunrise"]) + ", Sunset : " + (resp["sys"]["sunset"]) + "\n";
                Dictionary<string, object> resultjson = new Dictionary<string, object>();
                resultjson.Add("statuscode", 0);
                watch.Stop();
                resultjson.Add("data", responseData);
                resultjson.Add("exectime", watch.ElapsedMilliseconds);
                jsonstring = JsonConvert.SerializeObject(resultjson);
                await responsehandler.end(jsonstring);
            }
        } catch (Exception e) {
            Dictionary<string, object> resultjson = new Dictionary<string, object>();
            resultjson.Add("statuscode", 1);
            watch.Stop();
            resultjson.Add("data", "");
            resultjson.Add("exectime", watch.ElapsedMilliseconds);
            jsonstring = JsonConvert.SerializeObject(resultjson);
            await responsehandler.end(jsonstring);
        }
    }
}

// Define all exposed functions.
public void rpcfunction(object eventInfo)
{
    try {
        Action<object, object> icurrentWeather = this.currentWeather;
        (eventInfo as dBridges.remoteprocedure.Crpcserver).regfn("currentWeather", icurrentWeather);

    } catch (Exception e) {
        Console.WriteLine(e);
    }
}

// Initialize RPC Server weather.now.
this.rpcServer = dbridge.rpc.init("weather.now");

Action<object> ifunctions = this.rpcfunction;
this.rpcServer.functions = ifunctions;

// Register RPC Server with dBrdige network.
await this.rpcServer.register();

// Bind to server.registration.success, This will be triggered When summary is ready to serve.
Action<object, object> rconnectsuccess;
this.rpcServer.bind("dbridges:rpc.server.registration.success", rconnectsuccess = (object payload, object metadata) => {
    Console.WriteLine("dbridges:rpc.server.success {0} {1} {2} {3}", payload, metadata, this.rpcServer.getServerName(), this.rpcServer.isOnline());
});
// Bind to server.online, This will be triggered When summary is ready to serve.
Action<object, object> rconnectonline;
this.rpcServer.bind("dbridges:rpc.server.online", rconnectonline = (object payload, object metadata) => {
    Console.WriteLine("dbridges:rpc.server.online {0} {1} {2} {3}", payload, metadata, this.rpcServer.getServerName(), this.rpcServer.isOnline());
});
// Bind to server.registration.fail, This will be triggered When any registration issue is raised.
Action<object, object> rconnectfail;
this.rpcServer.bind("dbridges:rpc.server.registration.fail", rconnectfail = (object payload, object metadata) => {
    Console.WriteLine("dbridges:rpc.server.fail {0} {1} {2} {3}", payload, metadata, this.rpcServer.getServerName(), this.rpcServer.isOnline());
});

rpc.weather.client connects to weather.now RPC server and executes currentWeather function to get the result from openweathermap.org.

// Connect to weather.now server
weather = dbridge.rpc.connect("weather.now");
// We will bind to rpc server connection success event. On success, we will call remote functions.
weather.bind("dbridges:rpc.server.connect.success", () => {
    // Unary RPC: The client sends a single request and receives a single response.
    weather.call("currentWeather", cityName, 1000 * 60 * 2, null).then((response) => {
        const resp = JSON.parse(response);
        console.log(resp.data);
    }).catch((err) => {
        console.log(err);
    });
});
#  Connect to rpcServer
try:
    self.weather =  await self.dbridge.rpc.connect("weather.now")
except Exception as dberror:
    print("Exception: ", dberror.source, dberror.code, dberror.message)

if self.weather!= None:
    #  Bind to event server.connect.success, This will be triggered when the connection to server is successfull
    async def serverconnect_success(payload, metadata):
        print("dbridges:rpc.server.connect.success", payload, metadata)
        #  Execute Server function with parameter 
        await self.currentWeather()
    self.weather.bind("dbridges:rpc.server.connect.success", serverconnect_success)

    #  Bind to server.connect.fail. This will be triggered either if connection to rpcServer fails or reconnect fails.
    async def serverconnect_fail(payload, metadata):
        print("dbridges:rpc.server.connect.fail", payload, metadata)
    self.weather.bind("dbridges:rpc.server.connect.fail", serverconnect_fail)

async def currentWeather(self):
    try:
        #  Execute Server function with argument parameter .
        p = await self.weather.call('currentWeather', self.city, 10000, None)

        def onResult(res):
            #  Response will be received here. 
            print(res)

        def onError(res):
            #  Catch execption for .call
            print("Error", res.source, res.code, res.message, )

        p.then(onResult).catch(onError)

    except Exception as dberror:
        print("Exception: ", dberror.source, dberror.code, dberror.message)
dBridges.remoteprocedure.CrpCaller weather = null;
// Connect to rpcServer
try {
    weather = await dbridge.rpc.connect("weather.now");
} catch (dBridges.exceptions.dBError err)  {
    // Catch connect exception
    Console.WriteLine("dBridge rpc.connect exception {0} {1} {2}", err.source, err.code, err.message);
}

// Bind to event server.connect.success, This will be triggered when the connection to server is success
Action<object, object> connetsuccess;
weather.bind("dbridges:rpc.server.connect.success", connetsuccess = async (payload, metadata) => {
    // Execute Server function with parameter .
    IPromise<object> p = await weather.call("currentWeather", this.city, 1000 * 60 * 2, null);
    p.Then((response) => {
        Console.WriteLine("{1}", response);
    })
    .Catch((err) => {
        dBridges.exceptions.dBError er = err as dBridges.exceptions.dBError;
        Console.WriteLine("weather => exception {0} , {1} , {2}",  er.source, er.code, er.message);
    });
});

// Bind to server.connect.fail. This will be triggered either if connection to rpcServer fails or reconnect fails.
Action<object, object> connetfail;
weather.bind("dbridges:rpc.server.connect.fail", connetfail = (payload, metadata) => {
    dBridges.exceptions.dBError perror = payload as dBridges.exceptions.dBError;
    Console.WriteLine("dbridges:rpc.server.connect.fail {0} {1} {2} {3}", perror.source, perror.code, perror.message, metadata);
});

Running this example

You need to register at https://openweathermap.org/ and get an API AppID from openweathermap.org. We will be using this openweathermap.org API to fetch weather information.

You need to change few lines of code in both the files to replace your dataBridges appKey, appSecret and Authentication URL.

Edit rpc.weather.server and replace appkey ,appsecret and auth_url as shown below.

// Replace your dataBrdiges Application Key,Application Secret and Authentication URL below.
const dbApplnKey = 'appkey';
const dbAuthURL = 'auth_url';
const dbApplnSecret = 'appsecret';
const weatherAPPId = 'weather_APPID';
// Replace your dataBrdiges Application Key and Authentication URL below.
self.dbApplnKey = 'appkey'
self.dbAuthURL = 'auth_url'
self.dbApplnSecret = 'appsecret'
self.weatherAPPId = 'weather_APPID'
// Replace your dataBrdiges Application Key and Authentication URL below.
private string dbApplnKey = 'appkey';
private string dbAuthURL = 'auth_url';
private string dbApplnSecret = 'appsecret';
private string weatherAPPId = 'weather_APPID';
Properties Description
auth_url (string) Server authentication url from dataBridges dashboard.
appkey (string) Server application Key from dataBridges dashboard.
appsecret (string) Server application Secret from dataBridges dashboard.
weather_APPID (string) API AppID from openweathermap.org.

Edit rpc.weather.client and replace appkey and auth_url as shown below.

// Replace your dataBrdiges Application Key and Authentication URL below.
const dbApplnKey = 'appkey';
const dbAuthURL = 'auth_url';
// Replace your dataBrdiges Application Key and Authentication URL below.
self.dbApplnKey = 'appkey'
self.dbAuthURL = 'auth_url'
// Replace your dataBrdiges Application Key and Authentication URL below.
private string dbApplnKey = 'appkey';
private string dbAuthURL = 'auth_url';
Properties Description
auth_url (string) Client authentication url from dataBridges dashboard.
appkey (string) Client application Key from dataBridges dashboard.

Depending on the language you need to run two different instance of client and server program to test the above example.

After starting the server application, start rpc.weather.client with one argument i.e cityName for which the weather information has to be retrieved.

Understanding simulation output

Upon starting Server application will give below output.

Connection Connected aovAKhcfI0ZU6TQW8o8ad.5TG2h_j2PEB7ZdytAInc
dbridges:rpc.server.registration.success
dbridges:rpc.server.online

rpc.server.online event when shown in the output indicates the server is ready to serve RPC calls.

Upon starting Client application will give below output depending on cityName passed in the argument parameter . For below example we have passed Mumbai as argument parameter.

dBridge Event Bind connected nedfV3jrUkEg8cUDsJ7EX.Bbhf9t6sR-zKjAQSA7Wp true connected
Weather Condition : Smoke
Temprature : 29.99°C, feels like 29.16°C, humidity : 35
Pressure : 29.99 hPa , Visibility : 3000 meter, Cloudiness : 0 %
Wind : Speed 2.06 meter/sec , Wind direction : 290 °
Sunrise : 6:38:43 AM, Sunset : 6:05:33 PM