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
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:
-
Sign up for a dataBridges account.
-
Create a new app by selecting Apps and clicking Create New button.
-
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.
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.
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