adding agent source code

application-manager-new
GPrathap 9 years ago
parent 5dd57a157e
commit 3416a191c0

@ -1,4 +1,3 @@
#
# Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@ -12,18 +11,20 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#
[Device-Configurations]
server-name=${SERVER_NAME}
owner=${DEVICE_OWNER}
username=${DEVICE_OWNER}
deviceId=${DEVICE_ID}
device-name=${DEVICE_NAME}
manager-context=/doormanager/controller/get_user_info
controller-context=/doormanager/controller
https-ep=${HTTPS_EP}
http-ep=${HTTP_EP}
apim-ep=${APIM_EP}
mqtt-ep=${MQTT_EP}
auth-method=token
auth-token=${DEVICE_TOKEN}
refresh-token=${DEVICE_REFRESH_TOKEN}
push-interval=15

@ -1,16 +1,3 @@
#/*
# * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
# * WSO2 Inc. licenses this file to you under the Apache License,
# * Version 2.0 (the "License"); you may not use this file except
# * in compliance with the License.
# * You may obtain a copy of the License at
# * http://www.apache.org/licenses/LICENSE-2.0
# * Unless required by applicable law or agreed to in writing,
# * software distributed under the License is distributed on an
# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# * KIND, either express or implied. See the License for the
# * specific language governing permissions and limitations
# * under the License.
# */
templates=deviceConfig.properties
zipfilename=doormanager.zip

@ -0,0 +1,194 @@
#!/usr/bin/env python
"""
/**
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
**/
"""
import argparse
import httplib
import logging
import logging.handlers
import signal
import ssl
import sys
import threading
import time
from functools import wraps
import RPi.GPIO as GPIO
import MQTTHandler
import RFIDReader
import iotUtils
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Overriding the default SSL version used in some of the Python (2.7.x) versions
# This is a known issue in earlier Python releases
# But was fixed in later versions. Ex-2.7.11
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def sslwrap(func):
@wraps(func)
def bar(*args, **kw):
kw['ssl_version'] = ssl.PROTOCOL_TLSv1
return func(*args, **kw)
return bar
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PUSH_INTERVAL = 5000 # time interval between successive data pushes in seconds
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Logger defaults
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LOG_FILENAME = "DoorManagerAgent.log"
logging_enabled = False
LOG_LEVEL = logging.INFO # Could be e.g. "DEBUG" or "WARNING"
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Python version
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if sys.version_info < (2, 6, 0):
sys.stderr.write("You need python 2.6.0 or later to run this script\n")
exit(1)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Define and parse command line arguments
# If the log file is specified on the command line then override the default
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
parser = argparse.ArgumentParser(description="Python service to push RPi info to the Device Cloud")
parser.add_argument("-l", "--log", help="file to write log to (default '" + LOG_FILENAME + "')")
help_string_for_data_push_interval = "time interval between successive locker status push to server(default '" + str(
PUSH_INTERVAL) + "')"
parser.add_argument("-i", "--interval", type=int, help=help_string_for_data_push_interval)
args = parser.parse_args()
if args.log:
LOG_FILENAME = args.log
if args.interval:
PUSH_INTERVAL = args.interval
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# A class we can use to capture stdout and sterr in the log
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class IOTLogger(object):
def __init__(self, logger, level):
"""Needs a logger and a logger level."""
self.logger = logger
self.level = level
def write(self, message):
if message.rstrip() != "": # Only log if there is a message (not just a new line)
self.logger.log(self.level, message.rstrip())
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Configure logging to log to a file,
# making a new file at midnight and keeping the last 3 day's data
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def configureLogger(loggerName):
logger = logging.getLogger(loggerName)
logger.setLevel(LOG_LEVEL) # Set the log level to LOG_LEVEL
handler = logging.handlers.TimedRotatingFileHandler(LOG_FILENAME, when="midnight",
backupCount=3) # Handler that writes to a file,
# ~~~make new file at midnight and keep 3 backups
formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') # Format each log message like this
handler.setFormatter(formatter) # Attach the formatter to the handler
logger.addHandler(handler) # Attach the handler to the logger
if (logging_enabled):
sys.stdout = IOTLogger(logger, logging.INFO) # Replace stdout with logging to file at INFO level
sys.stderr = IOTLogger(logger, logging.ERROR) # Replace stderr with logging to file at ERROR level
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# This is a Thread object for reading RFID card
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class ListenRFIDhread(object):
def __init__(self):
thread = threading.Thread(target=self.run, args=())
thread.daemon = True # Daemonize thread
thread.start() # Start the execution
def run(self):
RFIDReader.main()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# This is a Thread object for listening for MQTT Messages
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class ListenMQTTThread(object):
def __init__(self):
thread = threading.Thread(target=self.run, args=())
thread.daemon = True # Daemonize thread
thread.start() # Start the execution
def run(self):
MQTTHandler.main()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# When sysvinit sends the TERM signal, cleanup before exiting
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def sigterm_handler(_signo, _stack_frame):
print("[] received signal {}, exiting...".format(_signo))
sys.exit(0)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
signal.signal(signal.SIGTERM, sigterm_handler)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# This method used to initialize GPIO ports
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def initDoorLock():
# GPIO.setmode(GPIO.BOARD)
GPIO.setup(iotUtils.DOOR_LOCKER_1_PORT, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(iotUtils.DOOR_LOCKER_2_PORT, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(iotUtils.LOCK_STATE_ON_NOTIFY_PORT, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(iotUtils.LOCK_STATE_OFF_NOTIFY_PORT, GPIO.OUT, initial=GPIO.LOW)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The Main method of the Automatic Door Locker Agent
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def main():
configureLogger("AutomaticDoorLocker")
ListenMQTTThread()
ListenRFIDhread()
initDoorLock()
# registerUIDofRFIDCard() # Call the register endpoint and register Device I
# ListenMQTTThread()
while True:
try:
time.sleep(PUSH_INTERVAL)
except (KeyboardInterrupt, Exception) as e:
print "AutomaticDoorLockerStats: Exception in RaspberryAgentThread (either KeyboardInterrupt or Other)"
print ("AutomaticDoorLockerStats: " + str(e))
print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
pass
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if __name__ == "__main__":
main()

@ -0,0 +1,396 @@
#!/usr/bin/env python
# -*- coding: utf8 -*-
import RPi.GPIO as GPIO
import spi
import signal
import time
class MFRC522:
NRSTPD = 22
MAX_LEN = 16
PCD_IDLE = 0x00
PCD_AUTHENT = 0x0E
PCD_RECEIVE = 0x08
PCD_TRANSMIT = 0x04
PCD_TRANSCEIVE = 0x0C
PCD_RESETPHASE = 0x0F
PCD_CALCCRC = 0x03
PICC_REQIDL = 0x26
PICC_REQALL = 0x52
PICC_ANTICOLL = 0x93
PICC_SElECTTAG = 0x93
PICC_AUTHENT1A = 0x60
PICC_AUTHENT1B = 0x61
PICC_READ = 0x30
PICC_WRITE = 0xA0
PICC_DECREMENT = 0xC0
PICC_INCREMENT = 0xC1
PICC_RESTORE = 0xC2
PICC_TRANSFER = 0xB0
PICC_HALT = 0x50
MI_OK = 0
MI_NOTAGERR = 1
MI_ERR = 2
Reserved00 = 0x00
CommandReg = 0x01
CommIEnReg = 0x02
DivlEnReg = 0x03
CommIrqReg = 0x04
DivIrqReg = 0x05
ErrorReg = 0x06
Status1Reg = 0x07
Status2Reg = 0x08
FIFODataReg = 0x09
FIFOLevelReg = 0x0A
WaterLevelReg = 0x0B
ControlReg = 0x0C
BitFramingReg = 0x0D
CollReg = 0x0E
Reserved01 = 0x0F
Reserved10 = 0x10
ModeReg = 0x11
TxModeReg = 0x12
RxModeReg = 0x13
TxControlReg = 0x14
TxAutoReg = 0x15
TxSelReg = 0x16
RxSelReg = 0x17
RxThresholdReg = 0x18
DemodReg = 0x19
Reserved11 = 0x1A
Reserved12 = 0x1B
MifareReg = 0x1C
Reserved13 = 0x1D
Reserved14 = 0x1E
SerialSpeedReg = 0x1F
Reserved20 = 0x20
CRCResultRegM = 0x21
CRCResultRegL = 0x22
Reserved21 = 0x23
ModWidthReg = 0x24
Reserved22 = 0x25
RFCfgReg = 0x26
GsNReg = 0x27
CWGsPReg = 0x28
ModGsPReg = 0x29
TModeReg = 0x2A
TPrescalerReg = 0x2B
TReloadRegH = 0x2C
TReloadRegL = 0x2D
TCounterValueRegH = 0x2E
TCounterValueRegL = 0x2F
Reserved30 = 0x30
TestSel1Reg = 0x31
TestSel2Reg = 0x32
TestPinEnReg = 0x33
TestPinValueReg = 0x34
TestBusReg = 0x35
AutoTestReg = 0x36
VersionReg = 0x37
AnalogTestReg = 0x38
TestDAC1Reg = 0x39
TestDAC2Reg = 0x3A
TestADCReg = 0x3B
Reserved31 = 0x3C
Reserved32 = 0x3D
Reserved33 = 0x3E
Reserved34 = 0x3F
serNum = []
def __init__(self, dev='/dev/spidev0.0', spd=1000000):
spi.openSPI(device=dev,speed=spd)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(22, GPIO.OUT)
GPIO.output(self.NRSTPD, 1)
self.MFRC522_Init()
def MFRC522_Reset(self):
self.Write_MFRC522(self.CommandReg, self.PCD_RESETPHASE)
def Write_MFRC522(self, addr, val):
spi.transfer(((addr<<1)&0x7E,val))
def Read_MFRC522(self, addr):
val = spi.transfer((((addr<<1)&0x7E) | 0x80,0))
return val[1]
def SetBitMask(self, reg, mask):
tmp = self.Read_MFRC522(reg)
self.Write_MFRC522(reg, tmp | mask)
def ClearBitMask(self, reg, mask):
tmp = self.Read_MFRC522(reg);
self.Write_MFRC522(reg, tmp & (~mask))
def AntennaOn(self):
temp = self.Read_MFRC522(self.TxControlReg)
if(~(temp & 0x03)):
self.SetBitMask(self.TxControlReg, 0x03)
def AntennaOff(self):
self.ClearBitMask(self.TxControlReg, 0x03)
def MFRC522_ToCard(self,command,sendData):
backData = []
backLen = 0
status = self.MI_ERR
irqEn = 0x00
waitIRq = 0x00
lastBits = None
n = 0
i = 0
if command == self.PCD_AUTHENT:
irqEn = 0x12
waitIRq = 0x10
if command == self.PCD_TRANSCEIVE:
irqEn = 0x77
waitIRq = 0x30
self.Write_MFRC522(self.CommIEnReg, irqEn|0x80)
self.ClearBitMask(self.CommIrqReg, 0x80)
self.SetBitMask(self.FIFOLevelReg, 0x80)
self.Write_MFRC522(self.CommandReg, self.PCD_IDLE);
while(i<len(sendData)):
self.Write_MFRC522(self.FIFODataReg, sendData[i])
i = i+1
self.Write_MFRC522(self.CommandReg, command)
if command == self.PCD_TRANSCEIVE:
self.SetBitMask(self.BitFramingReg, 0x80)
i = 2000
while True:
n = self.Read_MFRC522(self.CommIrqReg)
i = i - 1
if ~((i!=0) and ~(n&0x01) and ~(n&waitIRq)):
break
self.ClearBitMask(self.BitFramingReg, 0x80)
if i != 0:
if (self.Read_MFRC522(self.ErrorReg) & 0x1B)==0x00:
status = self.MI_OK
if n & irqEn & 0x01:
status = self.MI_NOTAGERR
if command == self.PCD_TRANSCEIVE:
n = self.Read_MFRC522(self.FIFOLevelReg)
lastBits = self.Read_MFRC522(self.ControlReg) & 0x07
if lastBits != 0:
backLen = (n-1)*8 + lastBits
else:
backLen = n*8
if n == 0:
n = 1
if n > self.MAX_LEN:
n = self.MAX_LEN
i = 0
while i<n:
backData.append(self.Read_MFRC522(self.FIFODataReg))
i = i + 1;
else:
status = self.MI_ERR
return (status,backData,backLen)
def MFRC522_Request(self, reqMode):
status = None
backBits = None
TagType = []
self.Write_MFRC522(self.BitFramingReg, 0x07)
TagType.append(reqMode);
(status,backData,backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, TagType)
if ((status != self.MI_OK) | (backBits != 0x10)):
status = self.MI_ERR
return (status,backBits)
def MFRC522_Anticoll(self):
backData = []
serNumCheck = 0
serNum = []
self.Write_MFRC522(self.BitFramingReg, 0x00)
serNum.append(self.PICC_ANTICOLL)
serNum.append(0x20)
(status,backData,backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE,serNum)
if(status == self.MI_OK):
i = 0
if len(backData)==5:
while i<4:
serNumCheck = serNumCheck ^ backData[i]
i = i + 1
if serNumCheck != backData[i]:
status = self.MI_ERR
else:
status = self.MI_ERR
return (status,backData)
def CalulateCRC(self, pIndata):
self.ClearBitMask(self.DivIrqReg, 0x04)
self.SetBitMask(self.FIFOLevelReg, 0x80);
i = 0
while i<len(pIndata):
self.Write_MFRC522(self.FIFODataReg, pIndata[i])
i = i + 1
self.Write_MFRC522(self.CommandReg, self.PCD_CALCCRC)
i = 0xFF
while True:
n = self.Read_MFRC522(self.DivIrqReg)
i = i - 1
if not ((i != 0) and not (n&0x04)):
break
pOutData = []
pOutData.append(self.Read_MFRC522(self.CRCResultRegL))
pOutData.append(self.Read_MFRC522(self.CRCResultRegM))
return pOutData
def MFRC522_SelectTag(self, serNum):
backData = []
buf = []
buf.append(self.PICC_SElECTTAG)
buf.append(0x70)
i = 0
while i<5:
buf.append(serNum[i])
i = i + 1
pOut = self.CalulateCRC(buf)
buf.append(pOut[0])
buf.append(pOut[1])
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf)
if (status == self.MI_OK) and (backLen == 0x18):
print "Size: " + str(backData[0])
return backData[0]
else:
return 0
def MFRC522_Auth(self, authMode, BlockAddr, Sectorkey, serNum):
buff = []
# First byte should be the authMode (A or B)
buff.append(authMode)
# Second byte is the trailerBlock (usually 7)
buff.append(BlockAddr)
# Now we need to append the authKey which usually is 6 bytes of 0xFF
i = 0
while(i < len(Sectorkey)):
buff.append(Sectorkey[i])
i = i + 1
i = 0
# Next we append the first 4 bytes of the UID
while(i < 4):
buff.append(serNum[i])
i = i +1
# Now we start the authentication itself
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_AUTHENT,buff)
# Check if an error occurred
if not(status == self.MI_OK):
print "AUTH ERROR!!"
if not (self.Read_MFRC522(self.Status2Reg) & 0x08) != 0:
print "AUTH ERROR(status2reg & 0x08) != 0"
# Return the status
return status
def MFRC522_StopCrypto1(self):
self.ClearBitMask(self.Status2Reg, 0x08)
def MFRC522_Read(self, blockAddr):
recvData = []
recvData.append(self.PICC_READ)
recvData.append(blockAddr)
pOut = self.CalulateCRC(recvData)
recvData.append(pOut[0])
recvData.append(pOut[1])
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, recvData)
if not(status == self.MI_OK):
print "Error while reading!"
i = 0
if len(backData) == 16:
print "Sector "+str(blockAddr)+" "+str(backData)
def MFRC522_Write(self, blockAddr, writeData):
buff = []
buff.append(self.PICC_WRITE)
buff.append(blockAddr)
crc = self.CalulateCRC(buff)
buff.append(crc[0])
buff.append(crc[1])
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buff)
if not(status == self.MI_OK) or not(backLen == 4) or not((backData[0] & 0x0F) == 0x0A):
status = self.MI_ERR
print str(backLen)+" backdata &0x0F == 0x0A "+str(backData[0]&0x0F)
if status == self.MI_OK:
i = 0
buf = []
while i < 16:
buf.append(writeData[i])
i = i + 1
crc = self.CalulateCRC(buf)
buf.append(crc[0])
buf.append(crc[1])
(status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE,buf)
if not(status == self.MI_OK) or not(backLen == 4) or not((backData[0] & 0x0F) == 0x0A):
print "Error while writing"
if status == self.MI_OK:
print "Data written"
def MFRC522_DumpClassic1K(self, key, uid):
i = 0
while i < 64:
status = self.MFRC522_Auth(self.PICC_AUTHENT1A, i, key, uid)
# Check if authenticated
if status == self.MI_OK:
self.MFRC522_Read(i)
else:
print "Authentication error"
i = i+1
def MFRC522_Init(self):
GPIO.output(self.NRSTPD, 1)
self.MFRC522_Reset();
self.Write_MFRC522(self.TModeReg, 0x8D)
self.Write_MFRC522(self.TPrescalerReg, 0x3E)
self.Write_MFRC522(self.TReloadRegL, 30)
self.Write_MFRC522(self.TReloadRegH, 0)
self.Write_MFRC522(self.TxAutoReg, 0x40)
self.Write_MFRC522(self.ModeReg, 0x3D)
self.AntennaOn()

@ -0,0 +1,131 @@
#!/usr/bin/env python
"""
/**
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
**/
"""
import time
import RPi.GPIO as GPIO
import paho.mqtt.client as mqtt
import iotUtils
global mqttClient
mqttClient = mqtt.Client()
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The callback for when the client receives a CONNACK response from the server.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def on_connect(mqttClient, userdata, flags, rc):
print("MQTT_LISTENER: Connected with result code " + str(rc))
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
print ("MQTT_LISTENER: Subscribing with topic " + TOPIC_TO_SUBSCRIBE)
mqttClient.subscribe(TOPIC_TO_SUBSCRIBE)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The callback for when a PUBLISH message is received from the server.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def on_message(mqttClient, userdata, msg):
print("MQTT_LISTENER: " + msg.topic + " " + str(msg.payload))
request = str(msg.payload)
resource = ""
if (len(request.split(":")) == 2):
resource = request.split(":")[0].upper()
state = request.split(":")[1].upper()
if state == "LOCK":
GPIO.output(iotUtils.DOOR_LOCKER_2_PORT, GPIO.HIGH)
GPIO.output(iotUtils.DOOR_LOCKER_1_PORT, GPIO.HIGH)
GPIO.output(iotUtils.LOCK_STATE_OFF_NOTIFY_PORT, GPIO.HIGH)
GPIO.output(iotUtils.LOCK_STATE_ON_NOTIFY_PORT, GPIO.LOW)
mqttClient.publish(TOPIC_TO_PUBLISH, "Locker:LOCKED")
print "Door is locked"
elif state == "UNLOCK":
GPIO.output(iotUtils.DOOR_LOCKER_2_PORT, GPIO.LOW)
GPIO.output(iotUtils.DOOR_LOCKER_1_PORT, GPIO.LOW)
GPIO.output(iotUtils.LOCK_STATE_OFF_NOTIFY_PORT, GPIO.LOW)
GPIO.output(iotUtils.LOCK_STATE_ON_NOTIFY_PORT, GPIO.HIGH)
mqttClient.publish(TOPIC_TO_PUBLISH, "Locker:UNLOCKED")
print "Door is unlocked"
else:
print "MQTT message in the wrong format"
print "MQTT_LISTENER: Resource- " + resource
else:
print "MQTT message in the wrong format"
print "MQTT_LISTENER: Resource- " + resource
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The callback for when a PUBLISH message to the server when door is open or close
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def on_publish(mqttClient, msg):
mqttClient.publish(TOPIC_TO_PUBLISH, msg)
def sendLockerStatus(msg):
global mqttClient
on_publish(mqttClient, msg)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# The Main method of the server script
# This method is invoked from DoorLockerAgent.py on a new thread
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def main():
MQTT_ENDPOINT = iotUtils.MQTT_EP.split(":")
MQTT_IP = MQTT_ENDPOINT[1].replace('//', '')
MQTT_PORT = int(MQTT_ENDPOINT[2])
DEV_OWNER = iotUtils.DEVICE_OWNER
DEV_ID = iotUtils.DEVICE_ID
global TOPIC_TO_SUBSCRIBE
TOPIC_TO_SUBSCRIBE = "wso2/iot/" + DEV_OWNER + "/doormanager/" + DEV_ID + "/subscriber"
global TOPIC_TO_PUBLISH
TOPIC_TO_PUBLISH = "wso2/iot/" + DEV_OWNER + "/doormanager/" + DEV_ID + "/publisher"
print ("MQTT_LISTENER: MQTT_ENDPOINT is " + str(MQTT_ENDPOINT))
print ("MQTT_LISTENER: MQTT_TOPIC is " + TOPIC_TO_SUBSCRIBE)
global mqttClient
mqttClient.on_connect = on_connect
mqttClient.on_message = on_message
while True:
try:
mqttClient.connect(MQTT_IP, MQTT_PORT, 60)
print "MQTT_LISTENER: " + time.asctime(), "Connected to MQTT Broker - %s:%s" % (MQTT_IP, MQTT_PORT)
# Blocking call that processes network traffic, dispatches callbacks and
# handles reconnecting.
# Other loop*() functions are available that give a threaded interface and a
# manual interface.
mqttClient.loop_forever()
except (KeyboardInterrupt, Exception) as e:
print "MQTT_LISTENER: Exception in MQTTServerThread (either KeyboardInterrupt or Other)"
print ("MQTT_LISTENER: " + str(e))
mqttClient.disconnect()
print "MQTT_LISTENER: " + time.asctime(), "Connection to Broker closed - %s:%s" % (MQTT_IP, MQTT_PORT)
print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
pass
if __name__ == '__main__':
main()

@ -0,0 +1,170 @@
#!/usr/bin/env python
"""
/**
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
**/
"""
import signal
import RPi.GPIO as GPIO
import MFRC522
import MQTTHandler
import iotUtils
import argparse
import httplib
import logging
import logging.handlers
import signal
import ssl
import sys
import threading
import time
from functools import wraps
CONTINUE_READING = True
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Overriding the default SSL version used in some of the Python (2.7.x) versions
# This is a known issue in earlier Python releases
# But was fixed in later versions. Ex-2.7.11
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def sslwrap(func):
@wraps(func)
def bar(*args, **kw):
kw['ssl_version'] = ssl.PROTOCOL_TLSv1
return func(*args, **kw)
return bar
# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
global CONTINUE_READING
print "Ctrl+C captured, ending read."
CONTINUE_READING = False
GPIO.cleanup()
# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)
# Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()
global RFID_CARD_UID
RFID_CARD_UID = ""
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Endpoint specific settings to connect with the IoT Server
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SERVER_ENDPOINT = iotUtils.HTTPS_EP.split(":")
SERVER_IP = SERVER_ENDPOINT[1].replace('//', '')
SERVER_PORT = int(SERVER_ENDPOINT[2])
API_ENDPOINT_CONTEXT = iotUtils.CONTROLLER_CONTEXT
REGISTER_ENDPOINT = str(API_ENDPOINT_CONTEXT) + '/register'
APIM_SERVER_ENDPOINT = iotUtils.API_EP.split(":")
APIM_SERVER_IP = APIM_SERVER_ENDPOINT[1].replace('//', '')
APIM_SERVER_PORT = int(APIM_SERVER_ENDPOINT[2])
MANAGER_API_CONTEXT = iotUtils.MANAGER_CONTEXT
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# This method check whether the UID of RFID card is registered or not
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def isRFIDCardRegistered( RFID_CARD_UID ):
ssl.wrap_socket = sslwrap(ssl.wrap_socket) # using the overridden sslwrap that uses TLSv1
print "Waiting to get UID of RFID card..."
if sys.version_info<(2,7,9):
dcConncection = httplib.HTTPSConnection(host=SERVER_IP, port=SERVER_PORT)
else:
dcConncection = httplib.HTTPSConnection(host=SERVER_IP, port=SERVER_PORT, context=ssl._create_unverified_context())
dcConncection.set_debuglevel(1)
dcConncection.connect()
PUSH_DATA = iotUtils.DEVICE_INFO_WITH_OWNER + iotUtils.DEVICE_DATA + RFID_CARD_UID
PUSH_DATA += '"}'
print PUSH_DATA
APIURL = str(MANAGER_API_CONTEXT)
dcConncection.putrequest('POST', APIURL)
dcConncection.putheader('Content-Type', 'application/json')
dcConncection.putheader('Authorization', 'Bearer ' + iotUtils.AUTH_TOKEN)
dcConncection.putheader('Content-Length', len(PUSH_DATA))
dcConncection.endheaders()
dcConncection.send(PUSH_DATA)
dcResponse = dcConncection.getresponse()
if(dcResponse.status < 250):
print "You are allowed to open the door"
isRegisteredUser = True
else:
isRegisteredUser = False
print "You are not allowed to open the door"
print ('DoorManager: ' + str(dcResponse.status))
print ('DoorManager: ' + str(dcResponse.reason))
print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
print ('DoorManager: ' + str(APIURL))
print ('DoorManager: Response Message')
print str(dcResponse.msg)
dcConncection.close()
print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'
return isRegisteredUser
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~------
# Read RFID card and if user is authorized to given RFID card, then open the lock
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~------
def readUIDofRFID():
print "-----------------------------------Starting MFRC522 chip reader---------------------------------------------"
# This loop keeps checking for chips. If one is near it will get the UID and authenticate
while CONTINUE_READING:
# Scan for cards
(status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)
# If a card is found
# Get the UID of the card
(status,uid) = MIFAREReader.MFRC522_Anticoll()
# If we have the UID, continue
if status == MIFAREReader.MI_OK:
global RFID_CARD_UID
RFID_CARD_UID = str(uid[0])+":"+str(uid[1])+":"+str(uid[2])+":"+str(uid[3])
print "Card read UID: " + RFID_CARD_UID
# This is the default key for authentication
key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]
# Select the scanned tag
MIFAREReader.MFRC522_SelectTag(uid)
# Authenticate
status = MIFAREReader.MFRC522_Auth(MIFAREReader.PICC_AUTHENT1A, 8, key, uid)
# Check if authenticated
if status == MIFAREReader.MI_OK:
MIFAREReader.MFRC522_Read(8)
MIFAREReader.MFRC522_StopCrypto1()
if(isRFIDCardRegistered(RFID_CARD_UID)):
print "Authentication successful"
GPIO.output(iotUtils.LOCK_STATE_OFF_NOTIFY_PORT, GPIO.LOW)
GPIO.output(iotUtils.LOCK_STATE_ON_NOTIFY_PORT, GPIO.HIGH)
GPIO.output(iotUtils.DOOR_LOCKER_2_PORT, GPIO.LOW)
GPIO.output(iotUtils.DOOR_LOCKER_1_PORT, GPIO.LOW)
MQTTHandler.on_publish(MQTTHandler.mqttClient,"Locker:UNLOCKED")
return True
def main():
global RFID_CARD_UID
RFID_CARD_UID = ""
readUIDofRFID()
if __name__ == '__main__':
main()

@ -0,0 +1,69 @@
#!/usr/bin/env python
"""
/**
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
**/
"""
import ConfigParser
import os
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Device specific info when pushing data to server
# Read from a file "deviceConfig.properties" in the same folder level
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
configParser = ConfigParser.RawConfigParser()
configFilePath = os.path.join(os.path.dirname(__file__), './deviceConfig.properties')
configParser.read(configFilePath)
DEVICE_OWNER = configParser.get('Device-Configurations', 'owner')
DEVICE_ID = configParser.get('Device-Configurations', 'deviceId')
SERIAL_NUMBER = configParser.get('Device-Configurations', 'deviceId')
MQTT_EP = configParser.get('Device-Configurations', 'mqtt-ep')
AUTH_TOKEN = configParser.get('Device-Configurations', 'auth-token')
USER_NAME = configParser.get('Device-Configurations', 'username')
CONTROLLER_CONTEXT = configParser.get('Device-Configurations', 'controller-context')
DEVICE_INFO = '{"owner":"' + DEVICE_OWNER + '","deviceId":"' + DEVICE_ID + '",'
HTTPS_EP = configParser.get('Device-Configurations', 'https-ep')
HTTP_EP = configParser.get('Device-Configurations', 'http-ep')
DEVICE_INFO_WITH_OWNER = '{"serialNumber":"' + SERIAL_NUMBER + '", "userName":"'+ USER_NAME +'","deviceId":"' + SERIAL_NUMBER + '",'
API_EP = configParser.get('Device-Configurations', 'apim-ep')
MANAGER_CONTEXT = configParser.get('Device-Configurations', 'manager-context')
DEVICE_DATA = '"cardNumber":"'
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
global IS_REGISTERED
IS_REGISTERED = False
DOOR_LOCKER_1_PORT = 16
DOOR_LOCKER_2_PORT = 18
LOCK_STATE_ON_NOTIFY_PORT = 11
LOCK_STATE_OFF_NOTIFY_PORT = 13
def isEmpty (string):
if string and string.strip():
#string is not None AND string is not empty or blank
return False
#string is None OR string is empty or blank
return True

@ -0,0 +1,59 @@
#"""
#/**
#* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
#*
#* WSO2 Inc. licenses this file to you under the Apache License,
#* Version 2.0 (the "License"); you may not use this file except
#* in compliance with the License.
#* You may obtain a copy of the License at
#*
#* http://www.apache.org/licenses/LICENSE-2.0
#*
#* Unless required by applicable law or agreed to in writing,
#* software distributed under the License is distributed on an
#* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#* KIND, either express or implied. See the License for the
#* specific language governing permissions and limitations
#* under the License.
#**/
#"""
#!/bin/bash
echo "----------------------------------------------------------------"
echo "| WSO2 IOT Door Manager "
echo "| Agent "
echo "| --------------------- "
echo "| ....initializing startup-script "
echo "----------------------------------------------------------------"
currentDir=$PWD
for f in ./deviceConfig.properties; do
## Check if the glob gets expanded to existing files.
## If not, f here will be exactly the pattern above
## and the exists test will evaluate to false.
if [ -e "$f" ]; then
echo "Configuration file found......"
else
echo "'deviceConfig.properties' file does not exist in current path. \nExiting installation...";
exit;
fi
## This is all we needed to know, so we can break after the first iteration
break
done
cd $currentDir
cp deviceConfig.properties ./src
chmod +x ./src/DoorManagerAgent.py
sudo python ./src/DoorManagerAgent.py
if [ $? -ne 0 ]; then
echo "Could not start the service..."
exit;
fi
echo "--------------------------------------"
echo "| Successfully Started "
echo "| -------------------------- "

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
@ -15,8 +16,13 @@
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.wso2</groupId>
<artifactId>wso2</artifactId>
<version>1</version>
</parent>
<groupId>org.homeautomation</groupId>
<artifactId>doormanager</artifactId>
<version>1.0.0-SNAPSHOT</version>
@ -140,11 +146,11 @@
<version>4.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.4</version>
</dependency>
</dependencies>
</dependencyManagement>
<pluginRepositories>
@ -234,14 +240,14 @@
<carbon.kernel.version>4.4.3</carbon.kernel.version>
<carbon.device.mgt.version>1.1.0-SNAPSHOT</carbon.device.mgt.version>
<carbon.device.mgt.jar.version>1.1.0.SNAPSHOT</carbon.device.mgt.jar.version>
<carbon-p2-plugin.version>1.5.3</carbon-p2-plugin.version>
<paho.mqtt.version>1.0.2</paho.mqtt.version>
<commons-json.version>3.0.0.wso2v1</commons-json.version>
<eclipse.osgi.version>3.8.1.v20120830-144521</eclipse.osgi.version>
<carbon.iot.device.mgt.version>1.9.2-SNAPSHOT</carbon.iot.device.mgt.version>
<carbon.iot.device.mgt.jar.version>1.9.2.SNAPSHOT</carbon.iot.device.mgt.jar.version>
<carbon.iot.device.mgt.version>2.0.4-SNAPSHOT</carbon.iot.device.mgt.version>
<carbon.iot.device.mgt.jar.version>2.0.4.SNAPSHOT</carbon.iot.device.mgt.jar.version>
<javax.ws.rs.version>1.1.1</javax.ws.rs.version>
<commons-io.version>2.4</commons-io.version>
<!--XMPP/MQTT Version-->
<smack.wso2.version>3.0.4.wso2v1</smack.wso2.version>
<smackx.wso2.version>3.0.4.wso2v1</smackx.wso2.version>
<cxf.version>2.6.1</cxf.version>

Loading…
Cancel
Save