Skip to content

Commit

Permalink
Merge pull request #10 from visionspacetec/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
milenko-s authored Oct 8, 2020
2 parents ab1cb43 + 16c65b0 commit 8953495
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 146 deletions.
168 changes: 53 additions & 115 deletions docs/QuickStartGuideLibreCube.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,90 +38,44 @@ python3 ~/sle-provider/examples/start_provider.py
docker-compose up --build -d
```

In any case, after start-up of the SLE provider, start the python-sle-user Return All Frames example:
In any case, after start-up of the SLE provider, create the python-sle-user Return All Frames example:

In *python-sle-user/examples/raf.py*:

```python
import logging; logging.basicConfig(level=logging.DEBUG)
import time
import sle
from config import config

raf = sle.RafUser(
service_instance_identifier=config['RAF']['RAF_INST_ID'],
responder_ip=config['RAF']['SLE_PROVIDER_HOSTNAME'],
responder_port=int(config['RAF']['SLE_PROVIDER_TM_PORT']),
auth_level='none',
local_identifier=config['RAF']['INITIATOR_ID'],
peer_identifier=config['RAF']['RESPONDER_ID'],
local_password=config['RAF']['PASSWORD'],
peer_password=config['RAF']['PEER_PASSWORD'],
heartbeat=25,
deadfactor=5,
buffer_size=4096,
version_number=2)

def return_data_handler(data):
print(data.prettyPrint())

raf.frame_handler = return_data_handler
raf.status_report_handler = return_data_handler
raf.parameter_handler = return_data_handler

def main():
raf.bind()
time.sleep(2)

if raf.state != 'ready':
print("Failed to bind to provider. Aborting...")
return

raf.start()
time.sleep(2)
raf_service = sle.RafUser(
service_instance_identifier="sagr=1.spack=VST-PASS0001.rsl-fg=1.raf=onlt1",
responder_ip="localhost",
responder_port=55529,
auth_level=None,
local_identifier="SLE_USER",
peer_identifier="SLE_PROVIDER",
local_password="",
peer_password="")

def print_data(data):
print(data.prettyPrint())

try:
while True:
time.sleep(0)
raf_service.frame_handler = print_data

except KeyboardInterrupt:
pass
raf_service.bind()
time.sleep(1)

finally:
if raf.state == 'active':
raf.stop()
time.sleep(2)
raf.schedule_status_report()
time.sleep(2)
raf.unbind(reason='other')
time.sleep(2)
input("Enter to start")
raf_service.start()
time.sleep(1)

main()
```
input("Enter to stop \n")
raf_service.stop()
time.sleep(1)

Fill the configuration parameters in *python-sle-user/examples/config.py*:
input("Enter to unbind")
raf_service.unbind()
time.sleep(1)

```python
config = {
"RAF": {
"RAF_INST_ID": "sagr=1.spack=VST-PASS0001.rsl-fg=1.raf=onlt1",
"SLE_PROVIDER_HOSTNAME": "localhost",
"SLE_PROVIDER_TM_PORT": "55529",
"INITIATOR_ID": "SLE_USER",
"RESPONDER_ID": "SLE_PROVIDER",
"PASSWORD": "",
"PEER_PASSWORD": "",
},
"CLTU": {
"CLTU_INST_ID": "sagr=1.spack=VST-PASS0001.fsl-fg=1.cltu=cltu1",
"SLE_PROVIDER_HOSTNAME": "localhost",
"SLE_PROVIDER_TC_PORT": "55529",
"INITIATOR_ID": "SLE_USER",
"RESPONDER_ID": "SLE_PROVIDER",
"PASSWORD": "",
"PEER_PASSWORD": "",
}
}
```

If you used the virtual environment installation procedure activate it and start the Return All Frames user:
Expand All @@ -147,62 +101,46 @@ After you finished this first example you can try out disabling frame generation
### FCLTU example
Change the docker entrypoint in the *docker-compose.yml* to **dockerfile: ./docker/frame_sending/Dockerfile**.


In *python-sle-user/examples/cltu.py*:
Create the file *python-sle-user/examples/cltu.py*:
```python
import logging; logging.basicConfig(level=logging.DEBUG)
import time
import sle
from config import config


cltu = sle.CltuUser(
service_instance_identifier=config['CLTU']['CLTU_INST_ID'],
responder_ip=config['CLTU']['SLE_PROVIDER_HOSTNAME'],
responder_port=int(config['CLTU']['SLE_PROVIDER_TC_PORT']),
auth_level='none',
local_identifier=config['CLTU']['INITIATOR_ID'],
peer_identifier=config['CLTU']['RESPONDER_ID'],
local_password=config['CLTU']['PASSWORD'],
peer_password=config['CLTU']['PEER_PASSWORD'],
heartbeat=25,
deadfactor=5,
buffer_size=256000,
version_number=2)


def return_data_handler(data):
cltu_service = sle.CltuUser(
service_instance_identifier="sagr=1.spack=VST-PASS0001.fsl-fg=1.cltu=cltu1",
responder_ip="localhost",
responder_port=55529,
auth_level=None,
local_identifier="SLE_USER",
peer_identifier="SLE_PROVIDER",
local_password="",
peer_password="")

def print_data(data):
print(data.prettyPrint())

cltu_service.status_report = print_data

cltu.status_report_handler = return_data_handler
cltu.parameter_handler = return_data_handler

cltu_service.bind()
time.sleep(1)

cltu.bind()
time.sleep(2)
cltu_service.schedule_status_report(report_type='periodically', cycle=10)

if cltu.state == 'ready':
cltu.start()
time.sleep(2)
input("Enter to start \n")
cltu_service.start()
time.sleep(1)

try:
cltu.transfer_data(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a")
time.sleep(2)
cltu.transfer_data(b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a")
time.sleep(2)
cltu = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" # dummy example
cltu_service.transfer_data(cltu)

except KeyboardInterrupt:
pass
input("Enter to stop")
cltu_service.stop()
time.sleep(1)

finally:
cltu.stop()
time.sleep(2)
cltu.unbind(reason='other') # avoid instance to be unloaded
time.sleep(2)
input("Enter to unbind")
cltu_service.unbind()
time.sleep(1)

else:
print("Failed binding to Provider. Aborting...")
```

Restart the SLE provider:
Expand All @@ -216,7 +154,7 @@ source ~/python-sle-user/venv/bin/activate
python ~/python-sle-user/examples/raf.py
```

The CLTU user will send two telecommands to the provider which are sent bach using a UDP loopback client. On the RAF user these frames are received again.
The CLTU user will send one telecommand to the provider which is sent back using a UDP loopback client. On the RAF user the frame is received again.
. Open a new terminal session for the second user:
```bash
source ~/python-sle-user/venv/bin/activate
Expand Down
151 changes: 135 additions & 16 deletions sleprovider/service/cltuProtocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,15 @@ def _initialise(self):
self.add_handler('CltuStartInvocation', self._start_invocation_handler)
self.add_handler('CltuStopInvocation', self._stop_invocation_handler)
self.add_handler('CltuTransferDataInvocation', self._transfer_data_invocation_handler)
# self.add_handler('RafScheduleStatusReportInvocation', self._schedule_status_report_invocation_handler)
self._production_status = 'operational'
self.add_handler('CltuScheduleStatusReportInvocation', self._schedule_status_report_invocation_handler)
self._cltu_last_processed = None
self._cltu_last_ok = None
self._cltu_production_status = 'operational'
self._uplink_status = 'nominal'
self._cltu_buffer_availiable = 4096 # ToDo: Read from service instance
self._number_of_cltus_received = 0
self._number_of_cltus_processed = 0
self._number_of_cltus_radiated = 0
self._transfer_buffer = None
self._release_timer = None
self._report_timer = None
Expand Down Expand Up @@ -157,27 +164,139 @@ def _transfer_data_invocation_handler(self, pdu):
else:
# ToDo: Implement produceNotification mechanism
raise NotImplementedError
self._number_of_cltus_received += 1
self.last_radiation_start_time = str(dt.datetime.utcnow()) # ToDo: How to find out when actually started?
str_time = dt.datetime.strptime(self.last_radiation_start_time, '%Y-%m-%d %H:%M:%S.%f')
time_days = (str_time - dt.datetime(1958, 1, 1)).days
time_ms = (str_time - dt.datetime(str_time.year, str_time.month, str_time.day)).seconds \
* 1000 + ((str_time - dt.datetime(str_time.year, str_time.month,
str_time.day)).microseconds // 1000)
time_micro = ((str_time -
dt.datetime(str_time.year, str_time.month, str_time.day)).microseconds
% 1000)
self.last_radiation_start_time = struct.pack('!HIH', time_days, time_ms, time_micro)
self._cltu_last_processed = self.cltu_identification # ToDo: Get feedback from data_endpoint if actually radiated

self.factory.container.data_endpoints[0].send_command('send-telecommand', [bytes(pdu['cltuData']).decode()])

self._number_of_cltus_processed += 1
self._number_of_cltus_radiated += 1 # ToDo: Get feedback from data_endpoint if actually radiated
self.last_radiation_stop_time = str(dt.datetime.utcnow()) # ToDo: How to find out when radiated?
str_time = dt.datetime.strptime(self.last_radiation_stop_time, '%Y-%m-%d %H:%M:%S.%f')
time_days = (str_time - dt.datetime(1958, 1, 1)).days
time_ms = (str_time - dt.datetime(str_time.year, str_time.month, str_time.day)).seconds \
* 1000 + ((str_time - dt.datetime(str_time.year, str_time.month,
str_time.day)).microseconds // 1000)
time_micro = ((str_time -
dt.datetime(str_time.year, str_time.month, str_time.day)).microseconds
% 1000)
self.last_radiation_stop_time = struct.pack('!HIH', time_days, time_ms, time_micro)
self._cltu_last_ok = self.cltu_identification # ToDo: Get feedback from data_endpoint if actually radiated

# ToDo: implement logic and different counting for return cltu identification if rejected
pdu_return['cltuIdentification'] = self.cltu_identification + 1
# ToDo: Implement buffer size
pdu_return['cltuBufferAvailable'] = 2048
pdu_return['cltuBufferAvailable'] = self._cltu_buffer_availiable
# ToDo: Negative result
pdu_return['result']['positiveResult'] = None
self._send_pdu(pdu_return)

# def _get_parameter_invocation_handler(self, pdu):
# pass

# def _schedule_status_report_invocation_handler(self, pdu):
# pass

# def _send_status_report(self):
# pass
def _schedule_status_report_invocation_handler(self, pdu):
logger.debug('Schedule Status Report Invocation received!')
pdu = pdu['cltuScheduleStatusReportInvocation']
pdu_return = CltuProviderToUserPdu()['cltuScheduleStatusReportReturn']
if 'used' in pdu['invokerCredentials']:
self._invoker_credentials = pdu['invokerCredentials']['used']
pdu_return['performerCredentials']['used'] = make_credentials(self.factory.container.local_id,
self.factory.container.local_password)
else:
self._invoker_credentials = None
pdu_return['performerCredentials']['unused'] = None
# ToDo: pdu_return['result']['negativeResult']['common'] = 'duplicateInvokeId'
pdu_return['invokeId'] = int(pdu['invokeId'])
if self.factory.container.si_config[self._inst_id]['state'] not in {'ready', 'active'}:
pdu_return['result']['negativeResult']['common'] = 'otherReason'
elif self.factory.container.remote_peers[self._initiator_id]['authentication_mode'] == \
'ALL' and not check_invoke_credentials(self._invoker_credentials,
self._initiator_id,
str(self.factory.container.remote_peers[
str(self._initiator_id)]['password'])):
pdu_return['result']['negativeResult']['common'] = 'otherReason'
elif 'periodically' in pdu['reportRequestType']:
if not (self.factory.container.min_reporting_cycle
<= int(pdu['reportRequestType']['periodically'])
<= self.factory.container.max_reporting_cycle):
pdu_return['result']['negativeResult']['specific'] = 'invalidReportingCycle'
else:
if self._report_timer is None:
self._report_timer = reactor.callLater(int(pdu['reportRequestType']['periodically']),
self._send_status_report)
self.factory.container.si_config[self._inst_id]['report_cycle'] = \
int(pdu['reportRequestType']['periodically'])
else:
self.factory.container.si_config[self._inst_id]['report_cycle'] = \
int(pdu['reportRequestType']['periodically'])
self._report_timer.reset(int(pdu['reportRequestType']['periodically']))
pdu_return['result']['positiveResult'] = None
elif 'stop' in pdu['reportRequestType']:
if self._report_timer is None:
pdu_return['result']['negativeResult']['specific'] = 'alreadyStopped'
else:
if (self._report_timer.called == 1) or (self._report_timer.cancelled == 1):
self._report_timer = None
pdu_return['result']['negativeResult']['specific'] = 'alreadyStopped'
else:
self._report_timer.cancel()
self._report_timer = None
pdu_return['result']['positiveResult'] = None
elif 'immediately' in pdu['reportRequestType']:
self._send_status_report()
if self._report_timer is not None:
if (self._report_timer.called == 1) or (self._report_timer.cancelled == 1):
self._report_timer = None
else:
self._report_timer.cancel()
self._report_timer = None
pdu_return['result']['positiveResult'] = None
else:
raise Exception()
self._send_pdu(pdu_return)

# def append_to_transfer_buffer(self, frame_or_notification):
# pass
def _send_status_report(self):
if self.factory.container.si_config[self._inst_id]['state'] not in {'ready', 'active'}:
logger.error('Can not send status report in state: {}'
.format(self.factory.container.si_config[self._inst_id]['state']))
return
pdu_invoc = CltuProviderToUserPdu()['cltuStatusReportInvocation']
if self.factory.container.remote_peers[self.factory.container.si_config[self._inst_id]['initiator_id']][
'authentication_mode'] == 'ALL':
pdu_invoc['invokerCredentials']['used'] = make_credentials(self.factory.container.local_id,
self.factory.container.local_password)
else:
pdu_invoc['invokerCredentials']['unused'] = None
if self._cltu_last_processed is None:
pdu_invoc['cltuLastProcessed']['noCltuProcessed'] = None
else:
pdu_invoc['cltuLastProcessed']['cltuProcessed']['cltuIdentification'] = self.cltu_identification
pdu_invoc['cltuLastProcessed']['cltuProcessed']['radiationStartTime']['known']['ccsdsFormat'] = \
self.last_radiation_start_time
pdu_invoc['cltuLastProcessed']['cltuProcessed']['cltuStatus'] = 'radiated' # ToDo: Relate to something
if self._cltu_last_ok is None:
pdu_invoc['cltuLastOk']['noCltuOk'] = None
else:
pdu_invoc['cltuLastOk']['cltuOk']['cltuIdentification'] = self.cltu_identification
pdu_invoc['cltuLastOk']['cltuOk']['radiationStopTime']['ccsdsFormat'] = \
self.last_radiation_stop_time
pdu_invoc['cltuProductionStatus'] = self._cltu_production_status
pdu_invoc['uplinkStatus'] = self._uplink_status
pdu_invoc['numberOfCltusReceived'] = self._number_of_cltus_received
pdu_invoc['numberOfCltusProcessed'] = self._number_of_cltus_processed
pdu_invoc['numberOfCltusRadiated'] = self._number_of_cltus_radiated
pdu_invoc['cltuBufferAvailable'] = self._cltu_buffer_availiable
self._send_pdu(pdu_invoc)
if self._report_timer is not None:
if self._report_timer.called == 1:
self._report_timer = reactor.callLater(self.factory.container.si_config[self._inst_id]['report_cycle'],
self._send_status_report)

# def _send_transfer_buffer(self):
# pass
# def _get_parameter_invocation_handler(self, pdu):
# pass
Loading

0 comments on commit 8953495

Please sign in to comment.