This repository hosts the source code for Python AASx Server,
1️⃣ The code is written in Python 3.9
2️⃣ All the Python dependencies are specified in the requirements.txt
3️⃣ The LIA OVGU development uses eclipse editor, accordingly eclipse related project files are provided in the repository.
pip3 install -r requirements.txt
The source code is associated with a .env file, all the configuration variables are specified in it.
LIA_AAS_RESTAPI_DOMAIN_INTERN=localhost
LIA_AAS_RESTAPI_DOMAIN_EXTERN=localhost
LIA_AAS_RESTAPI_PORT_EXTERN=60012
LIA_AAS_RESTAPI_PORT_INTERN=60012
LIA_AAS_MQTT_HOST=localhost
LIA_AAS_MQTT_PORT=1883
LIA_preferedI40EndPoint=MQTT
LIA_REGISTRYENDPOINT=http://liabroker.ddns.net:9021/i40commu
LIA_AAS_PACKAGE=AAS_LIA_Demonstrator.json
LIA_PUBSUB_LISTNER_HOST=localhost
LIA_PUBSUB_LISTNER_PORT=4051
LIA_SECURITY_ENABLED=Y
LIA_AUTHENTICATION_SERVER=22
LIA_PATH2SIGNINGKEY=identityserver.test.rsa.pem
LIA_PATH2AUTHCERT=identityserver.test.rsa.cer
LIA_NAMESPACE=ovgu.de
- The base python program is organized inside the src/main subdirectory.
python3.9 pyaasxServer.py
The table 2 provides list of rest services the Python AASx Serve rprovides, it also lists down the allowed operations for each of the service. The services are as per the guidelines of AAS Detail Part 2.
{aasIdentifier} = idShort or global unique identifier of AAS or global unique identifier of the aaset that the AAS is representing
{submodelIdentifier} = idShort or global unique identifier of Submodel
In PythonAASxServer the concept skills represent the behavior of the type 3 AAS. These skills are modelled as Finite State Machines (FSM). The interactions between the skills happens with exchange the [I4.0 Messages](https://github.com/harishpakala/I40_Language_Semantics)
Interaction Protocols represent structured sequence of messages exchanged between multiple partners / actors to achieve a specified goal (Example : Three-Way Handhake Protocol). An instance / execution of an interaction protocol is associated with a specific conversationID, all the messages wihtin the concersation have the same conversationID within I4.0 frame part. Each skilll in a Interaction Protocol is specific Role Name. There could be multiple skills with same Role Name.
The Python source-code created by the state machine creator contains a set of classes. Each state represents a specific state and the entire state machine is represensted by anotehr class, that coordinates it's execution.
Each skill / FSM is associated with a specific queue within in the PythonAASxServer framework.
Transitions between the states are expected due to one of the three event-types a) Inbound Message, b) Internal Trigger c) External Trigger.
class Hello(AState):
message_in = ["Ping",]
def initialize(self):
# Gaurd variables for enabling the transitions
self.SendAck_Enabled = True
def actions(self) -> None:
if (self.wait_untill_timeout(10)):
message = self.receive(WaitforHi.message_in[0])
self.save_in_message(message)
def transitions(self) -> object:
if (self.SendAck_Enabled):
return "SendAck"
A Hello state formatted as per Pyhton AASxServer and the StateMachine creator.
- The Hello state inherits the class Abstract class AState source-code.
- The static variable message_in represents the list of messages that the FSM is expected to receive in the specific state.
- This class provides a set of guard conditions reequired for transitions to the next state. All the logic to the be executed within the Hello state needs to be written in the actions() method.
- The transitions() method should not be edited.
- For every next state a boolean guard variable will be provided in the constructor of the class, extracted from the JSON file. All the guard variables are defaulted to True.
- The developer needs to disable gaurd variable (False) in the actions() method, for the state that is not the next one.
- The PythonAASxServer framework takes care and hide the complete mechanism behind the exchange of I4.0 messages between the skills.
receive(msg_in)
Returns the first message from the inbound queue of type msg_in, if there is no message the method returns None.
receive_all(msg_in)
Returns all the messages from the inbound queue of type msg_in, if there is no message the method returns an empty list.
create_i40_message(msg_out,conversationId,receiverId,receiverRole)
Creates an I4.0 message of type 'msg_out' with a specific 'conversationId'. The senderRole will the SKill that has called this method. The receiverRole is destination skill. The combination of receiverId and receiverRole is expected to be unique within the specific interaction. The senderId or the receiverId represents unique Id of the type3 AAS to which the SKill is attached.
save_in_message(msg)
Copies the contents of an inbound I4.0 messsage to backend.
save_out_message(msg_in)
Copies the contents of an outbound I4.0 messsage to backend.
GetSubmodelById(submodelId)
Returns the submodel of the specified submodelId. In case the submodel is not present or any internal error it returns error.
GetSubmodelELementByIdshoortPath(submodelId)
Returns the submodel-element of the specified submodelId and IdShortPath combination. In case the submodel-element is not present or any internal error it returns error.
save_submodel(submodel)
The replaces the existing submodel with the new submodel specified. Successful updation will return True, else returns False.
wait_untill_timeout(timer)
The Control waits untill a specific number of seconds as assigned to argument to the method.
wait_untill_message(message_count,msg_types)
The Control waits untill a specific number of messaages are arrived in the buffer of the message type specified as an argument msg_types (List of strings).
wait_untill_message_timeout(message_count,timer,msg_types)
The Control waits untill a specific number of messaages are arrived in the buffer of the message type specified as an argument msg_types (List of strings). However if the timer expires, the control returns.
Every FSM skill is provided by tape by the PythonAASxServer framework. Each entry in the tape is key value pair.
push(key,value)
Push a data element 'value' to the tape with an associated 'key'.
retrieve(key)
Returns the value associated with the specific key.
flush()
Clears the tapes, removes all the key,value pairs. Usually it is done afer an iteration of the FSM.
class AccessProvider(Actor): ''' classdocs '''
def __init__(self):
'''
Constructor
'''
Actor.__init__(self,"AccessProvider",
"www.admin-shell.io/interaction/3WayHandshake",
"Access Provision","Start")
def start(self):
self.run("Start")
The python project maintains a logger, all the important aspects regarding its functionality are captured with logger. The entire log information is stored into .LOG files under the src > main > logs folder.
If you want to request new features or report bug submit a new issue
Python AAS Registry is Licensed under Apache 2.0, the complete license text including the copy rights is included under License.txt
- APScheduler,python-snap7,jsonschema,aiocoap,hbmqtt MIT License
- Flask,werkzeug, Flask-RESTful, python-dotenv BSD-3-Clause
- requests Apache License, Version 2.0
- paho-mqtt Eclipse Public License 2.0 and the Eclipse Distribution License 1.0