Merge pull request #735 from Savidude/master

Auto renewal of auth token for RaspberryPi agent
merge-requests/1/head
Rasika Perera 8 years ago committed by GitHub
commit d7b8e32744

@ -110,8 +110,8 @@ public class RaspberryPiServiceImpl implements RaspberryPiService {
@Produces("application/json") @Produces("application/json")
public Response getRaspberryPiTemperatureStats(@PathParam("deviceId") String deviceId, public Response getRaspberryPiTemperatureStats(@PathParam("deviceId") String deviceId,
@QueryParam("from") long from, @QueryParam("to") long to) { @QueryParam("from") long from, @QueryParam("to") long to) {
String fromDate = String.valueOf(from); String fromDate = String.valueOf(from*1000);
String toDate = String.valueOf(to); String toDate = String.valueOf(to*1000);
String query = "meta_deviceId:" + deviceId + " AND meta_deviceType:" + String query = "meta_deviceId:" + deviceId + " AND meta_deviceType:" +
RaspberrypiConstants.DEVICE_TYPE + " AND meta_time : [" + fromDate + " TO " + toDate + "]"; RaspberrypiConstants.DEVICE_TYPE + " AND meta_time : [" + fromDate + " TO " + toDate + "]";
String sensorTableName = RaspberrypiConstants.TEMPERATURE_EVENT_TABLE; String sensorTableName = RaspberrypiConstants.TEMPERATURE_EVENT_TABLE;
@ -121,7 +121,7 @@ public class RaspberryPiServiceImpl implements RaspberryPiService {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build(); return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
} }
List<SortByField> sortByFields = new ArrayList<>(); List<SortByField> sortByFields = new ArrayList<>();
SortByField sortByField = new SortByField("time", SortType.ASC); SortByField sortByField = new SortByField("meta_time", SortType.ASC);
sortByFields.add(sortByField); sortByFields.add(sortByField);
List<SensorRecord> sensorRecords = APIUtil.getAllEventsForDevice(sensorTableName, query, sortByFields); List<SensorRecord> sensorRecords = APIUtil.getAllEventsForDevice(sensorTableName, query, sortByFields);
return Response.status(Response.Status.OK.getStatusCode()).entity(sensorRecords).build(); return Response.status(Response.Status.OK.getStatusCode()).entity(sensorRecords).build();
@ -221,7 +221,7 @@ public class RaspberryPiServiceImpl implements RaspberryPiService {
String refreshToken = accessTokenInfo.getRefreshToken(); String refreshToken = accessTokenInfo.getRefreshToken();
ZipUtil ziputil = new ZipUtil(); ZipUtil ziputil = new ZipUtil();
return ziputil.createZipFile(owner, APIUtil.getTenantDomainOftheUser(), sketchType, return ziputil.createZipFile(owner, APIUtil.getTenantDomainOftheUser(), sketchType,
deviceId, deviceName, accessToken, refreshToken); deviceId, deviceName, accessToken, refreshToken, apiApplicationKey.toString());
} }
private static String shortUUID() { private static String shortUUID() {

@ -18,9 +18,12 @@
package org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl.util; package org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl.util;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.json.JSONObject;
import org.wso2.carbon.apimgt.application.extension.constants.ApiApplicationConstants;
import org.wso2.carbon.core.util.Utils; import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
@ -61,7 +64,7 @@ public class ZipUtil {
public ZipArchive createZipFile(String owner, String tenantDomain, String deviceType, public ZipArchive createZipFile(String owner, String tenantDomain, String deviceType,
String deviceId, String deviceName, String token, String deviceId, String deviceName, String token,
String refreshToken) throws DeviceManagementException { String refreshToken, String apiApplicationKey) throws DeviceManagementException {
String sketchFolder = "repository" + File.separator + "resources" + File.separator + "sketches"; String sketchFolder = "repository" + File.separator + "resources" + File.separator + "sketches";
String templateSketchPath = sketchFolder + File.separator + deviceType; String templateSketchPath = sketchFolder + File.separator + deviceType;
@ -96,6 +99,7 @@ public class ZipUtil {
} }
} }
} }
String base64EncodedApplicationKey = getBase64EncodedAPIAppKey(apiApplicationKey);
Map<String, String> contextParams = new HashMap<>(); Map<String, String> contextParams = new HashMap<>();
contextParams.put("SERVER_NAME", APIUtil.getTenantDomainOftheUser()); contextParams.put("SERVER_NAME", APIUtil.getTenantDomainOftheUser());
@ -106,6 +110,7 @@ public class ZipUtil {
contextParams.put("HTTP_EP", httpServerEP); contextParams.put("HTTP_EP", httpServerEP);
contextParams.put("APIM_EP", httpsServerEP); contextParams.put("APIM_EP", httpsServerEP);
contextParams.put("MQTT_EP", mqttEndpoint); contextParams.put("MQTT_EP", mqttEndpoint);
contextParams.put("API_APPLICATION_KEY", base64EncodedApplicationKey);
contextParams.put("DEVICE_TOKEN", token); contextParams.put("DEVICE_TOKEN", token);
contextParams.put("DEVICE_REFRESH_TOKEN", refreshToken); contextParams.put("DEVICE_REFRESH_TOKEN", refreshToken);
@ -119,6 +124,15 @@ public class ZipUtil {
} }
} }
private String getBase64EncodedAPIAppKey(String apiAppCredentialsAsJSONString) {
JSONObject jsonObject = new JSONObject(apiAppCredentialsAsJSONString);
String consumerKey = jsonObject.get(ApiApplicationConstants.OAUTH_CLIENT_ID).toString();
String consumerSecret = jsonObject.get(ApiApplicationConstants.OAUTH_CLIENT_SECRET).toString();
String stringToEncode = consumerKey + ":" + consumerSecret;
return Base64.encodeBase64String(stringToEncode.getBytes());
}
private static String getServerUrl() { private static String getServerUrl() {
try { try {
return org.apache.axis2.util.Utils.getIpAddress(); return org.apache.axis2.util.Utils.getIpAddress();

@ -20,14 +20,12 @@ owner=${DEVICE_OWNER}
deviceId=${DEVICE_ID} deviceId=${DEVICE_ID}
device-name=${DEVICE_NAME} device-name=${DEVICE_NAME}
controller-context=/raspberrypi/controller controller-context=/raspberrypi/controller
mqtt-sub-topic=${SERVER_NAME}/{owner}/raspberrypi/{deviceId}
mqtt-pub-topic=${SERVER_NAME}/{owner}/raspberrypi/{deviceId}/publisher
https-ep=${HTTPS_EP} https-ep=${HTTPS_EP}
http-ep=${HTTP_EP} http-ep=${HTTP_EP}
apim-ep=${APIM_EP} apim-ep=${APIM_EP}
mqtt-ep=${MQTT_EP} mqtt-ep=${MQTT_EP}
xmpp-ep=${XMPP_EP}
auth-method=token auth-method=token
application-key=${API_APPLICATION_KEY}
auth-token=${DEVICE_TOKEN} auth-token=${DEVICE_TOKEN}
refresh-token=${DEVICE_REFRESH_TOKEN} refresh-token=${DEVICE_REFRESH_TOKEN}
push-interval=15 push-interval=15

@ -182,9 +182,6 @@ def connectAndPushData():
rPiTemperature = iotUtils.LAST_TEMP # Push the last read temperature value rPiTemperature = iotUtils.LAST_TEMP # Push the last read temperature value
PUSH_DATA = iotUtils.DEVICE_INFO.format(currentTime, rPiTemperature) PUSH_DATA = iotUtils.DEVICE_INFO.format(currentTime, rPiTemperature)
print '~~~~~~~~~~~~~~~~~~~~~~~~ Publishing Device-Data ~~~~~~~~~~~~~~~~~~~~~~~~~'
print ('PUBLISHED DATA: ' + PUSH_DATA)
print ('PUBLISHED TOPIC: ' + mqttConnector.TOPIC_TO_PUBLISH)
mqttConnector.publish(PUSH_DATA) mqttConnector.publish(PUSH_DATA)
# print '~~~~~~~~~~~~~~~~~~~~~~~~ End Of Publishing ~~~~~~~~~~~~~~~~~~~~~~~~~' # print '~~~~~~~~~~~~~~~~~~~~~~~~ End Of Publishing ~~~~~~~~~~~~~~~~~~~~~~~~~'

@ -56,11 +56,10 @@ SERVER_NAME = configParser.get('Device-Configurations', 'server-name')
DEVICE_OWNER = configParser.get('Device-Configurations', 'owner') DEVICE_OWNER = configParser.get('Device-Configurations', 'owner')
DEVICE_ID = configParser.get('Device-Configurations', 'deviceId') DEVICE_ID = configParser.get('Device-Configurations', 'deviceId')
MQTT_EP = configParser.get('Device-Configurations', 'mqtt-ep') MQTT_EP = configParser.get('Device-Configurations', 'mqtt-ep')
XMPP_EP = configParser.get('Device-Configurations', 'xmpp-ep')
AUTH_TOKEN = configParser.get('Device-Configurations', 'auth-token') AUTH_TOKEN = configParser.get('Device-Configurations', 'auth-token')
REFRESH_TOKEN = configParser.get('Device-Configurations', 'refresh-token')
APPLICATION_KEY = configParser.get('Device-Configurations', 'application-key')
CONTROLLER_CONTEXT = configParser.get('Device-Configurations', 'controller-context') CONTROLLER_CONTEXT = configParser.get('Device-Configurations', 'controller-context')
MQTT_SUB_TOPIC = configParser.get('Device-Configurations', 'mqtt-sub-topic').format(owner = DEVICE_OWNER, deviceId = DEVICE_ID)
MQTT_PUB_TOPIC = configParser.get('Device-Configurations', 'mqtt-pub-topic').format(owner = DEVICE_OWNER, deviceId = DEVICE_ID)
DEVICE_INFO = '{{"event":{{"metaData":{{"owner":"' + DEVICE_OWNER + '","type":"raspberrypi","deviceId":"' + DEVICE_ID + '","time":{}}},"payloadData":{{"temperature":{:.2f}}}}}}}' DEVICE_INFO = '{{"event":{{"metaData":{{"owner":"' + DEVICE_OWNER + '","type":"raspberrypi","deviceId":"' + DEVICE_ID + '","time":{}}},"payloadData":{{"temperature":{:.2f}}}}}}}'
# '{"owner":"' + DEVICE_OWNER + '","deviceId":"' + DEVICE_ID + '","temperature":' # '{"owner":"' + DEVICE_OWNER + '","deviceId":"' + DEVICE_ID + '","temperature":'

@ -23,16 +23,29 @@
import time import time
import iotUtils import iotUtils
import paho.mqtt.client as mqtt import paho.mqtt.client as mqtt
from token_updater import RefreshToken
agent_connected = False
# The callback for when the client receives a CONNACK response from the server. # The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc): def on_connect(client, userdata, flags, rc):
print("MQTT_LISTENER: Connected with result code " + str(rc)) if rc == 0:
global agent_connected
agent_connected = True
# Subscribing in on_connect() means that if we lose the connection and # Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed. # reconnect then subscriptions will be renewed.
print ("MQTT_LISTENER: Subscribing with topic " + TOPIC_TO_SUBSCRIBE) print ("MQTT_LISTENER: Subscribing with topic " + TOPIC_TO_SUBSCRIBE)
client.subscribe(TOPIC_TO_SUBSCRIBE) client.subscribe(TOPIC_TO_SUBSCRIBE)
elif rc == 4:
token = RefreshToken()
response = token.updateTokens()
newAccessToken = response['access_token']
client.username_pw_set(newAccessToken, password="")
else:
global agent_connected
agent_connected = False
print("MQTT_LISTENER: Connected with result code " + str(rc))
@ -72,12 +85,28 @@ def on_publish(client, userdata, mid):
# The callback for when a PUBLISH message to the server when door is open or close # The callback for when a PUBLISH message to the server when door is open or close
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def publish(msg): def publish(msg):
if agent_connected:
print '~~~~~~~~~~~~~~~~~~~~~~~~ Publishing Device-Data ~~~~~~~~~~~~~~~~~~~~~~~~~'
print ('PUBLISHED DATA: ' + msg)
print ('PUBLISHED TOPIC: ' + TOPIC_TO_PUBLISH)
global mqttClient global mqttClient
mqttClient.publish(TOPIC_TO_PUBLISH, msg) mqttClient.publish(TOPIC_TO_PUBLISH, msg)
def on_subscribe(client, userdata, mid, granted_qos): def on_subscribe(client, userdata, mid, granted_qos):
print "Successfully subscribed to " + TOPIC_TO_SUBSCRIBE print "Successfully subscribed to " + TOPIC_TO_SUBSCRIBE
def on_disconnect(client, userdata, rc):
global agent_connected
agent_connected = False
print ("Agent disconnected from broker")
print("Obtaining new access token")
token = RefreshToken()
response = token.updateTokens()
newAccessToken = response['access_token']
client.username_pw_set(newAccessToken, password="")
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The Main method of the server script # The Main method of the server script
# This method is invoked from RaspberryStats.py on a new thread # This method is invoked from RaspberryStats.py on a new thread
@ -106,6 +135,7 @@ def main():
mqttClient.on_message = on_message mqttClient.on_message = on_message
mqttClient.on_publish = on_publish mqttClient.on_publish = on_publish
mqttClient.on_subscribe = on_subscribe mqttClient.on_subscribe = on_subscribe
mqttClient.on_disconnect = on_disconnect
mqttClient.username_pw_set(iotUtils.AUTH_TOKEN, password = "") mqttClient.username_pw_set(iotUtils.AUTH_TOKEN, password = "")
while True: while True:
@ -132,4 +162,3 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
iotUtils.setUpGPIOPins() iotUtils.setUpGPIOPins()
main() main()

@ -0,0 +1,53 @@
import json
import urllib
import iotUtils
import requests
applicationKey = None
refreshToken = None
filename = "deviceConfig.properties"
class RefreshToken():
def post(self, url, payload, appKey):
headers = { 'Authorization' : 'Basic ' + appKey, 'Content-Type' : 'application/x-www-form-urlencoded' }
baseUrl = iotUtils.HTTP_EP + url
response = requests.post(baseUrl, params=payload, headers=headers);
return response
def read_server_conf(self):
with open(filename, 'r') as outfile:
conf_file = outfile.readlines()
return conf_file
def updateFile(self, response):
newRefreshToken = response['refresh_token']
newAccessToken = response['access_token']
with open(filename, 'r+') as f:
lines = f.readlines()
f.seek(0)
f.truncate()
for line in lines:
if line.__contains__("auth-token="):
line = "auth-token=" + newAccessToken + "\n"
if line.__contains__("refresh-token="):
line = "refresh-token=" + newRefreshToken + "\n"
f.write(line)
def updateTokens(self,):
global applicationKey
global refreshToken
refreshToken = iotUtils.REFRESH_TOKEN
applicationKey = iotUtils.APPLICATION_KEY
params = urllib.urlencode({"grant_type": "refresh_token", "refresh_token": refreshToken,
"scope": "Enroll device"})
data = self.post("/token", params, applicationKey)
response = json.loads(data)
self.updateFile(response)
return response
Loading…
Cancel
Save