Tutorial 4: Complete workbench process

In this tutorial, the engineering workbench will be completed in its initial version. By the end of this tutorial, you will have added the final piece of the workbench and be able to communicate with it. In this tutorial, we will also give two options for the satellite component of the workbench.
The first option is the recommended one if possible. It involves setting up a BeagleBone Black board with KubOS Linux and linking that with the workbench. The second would be ideal for someone awaiting hardware. It involves creating a series of Flask applications to imitate the services given in KubOS. This, however, is not very robust and would prevent proper development of your commands for your satellite.

KubOS OBC setup

For a detailed explanation on how to set up KubOS for any device, see the documentation here. This tutorial will give an explanation on how KubOS was set up and installed to a Beagle Bone Black and how it was configured to run this tutorial.

Prerequisites

  • An OBC; for our example, we used a Beagle Bone Black Rev. C. These steps are not guaranteed for other boards,
  • a microSD card for the BBB with at least 4GB of storage,
  • and the relevant images of KubOS Linux (found here)

Install the eMMC image

To do this, we flashed the SD card as per the documentation. We used Etcher as that is the KubOS software of choice, however, Rufus does provide a reliable alternative.
To flash the SD card, simply open up Etcher and follow the prompts. Firstly, you will need to select the image file you want to flash. For this step, this will be kubos-linux.img.
Once this is done, all four lights should turn on after a successful flashing. If all lights turn off on the beagle, you will need to re-flash the eMMC.

Install the auxiliary image

Following this, remove the microSD card and plug it back into your computer as we are now going to flash it with the auxiliary image (aux-sd.img). After this, plug the microSD card back into the Beagle and apply power.
The board will then go through its booting sequence and will likely take up to an hour to boot up the program. Once this is complete, you can then SSH into the Beagle and begin working with KubOS.
For more information on this and how to use KubOS, go to the documentation via the link above.

KubOS placeholder construction and setup

In the situation where we might not be able to run a local instance of KubOS, or we do not have an OBC available, we can develop our own applications to act as the satellite's services until such time a better replacement can be found. It must be noted that these applications are very basic and are only designed to receive pings. The services used in the examples given in the Javelin folder and in these tutorials are the app, monitor, schedule, and telemetry services. These are going to be recreated here.

App service

The following script mimics the application service in its most basic format using Flask
1
import time
2
from flask import Flask
3
import json
4
5
6
app = Flask('__name__')
7
8
9
@app.route('/', methods=["GET", "POST", "PUT"])
10
def receive_ping_to_service():
11
time.sleep(3)
12
# message = {"response": "Ping Received, Hello down there from the app service!!"} message = {"response": "Pong"}
13
json_string = json.dumps(message)
14
return json_string
15
16
17
if __name__ == '__main__':
18
app.run(port=8000)

Monitor service

In a similar way, the monitoring service can be modelled by
1
import time
2
from flask import Flask
3
import json
4
5
6
app = Flask('__name__')
7
8
9
@app.route('/', methods=["GET", "POST", "PUT"])
10
def receive_ping_to_service():
11
time.sleep(3)
12
# message = {"response": "Ping Received, Hello down there from the monitor service!!"}
13
message = {"response": "Pong"}
14
json_string = json.dumps(message)
15
return json_string
16
17
18
if __name__ == '__main__':
19
app.run(port=8030)

Scheduler service

The scheduler service is modelled by
1
import time
2
from flask import Flask
3
import json
4
5
6
app = Flask('__name__')
7
8
9
@app.route('/', methods=["GET", "POST", "PUT"])
10
def receive_ping_to_service():
11
time.sleep(3)
12
# message = {"response": "Ping Received, Hello down there from the scheduler service!!"}
13
message = {"response": "Pong"}
14
json_string = json.dumps(message)
15
return json_string
16
17
18
if __name__ == '__main__':
19
app.run(port=8060)

Telemetry service

Finally, the telemetry service is modelled by
1
import time
2
from flask import Flask
3
import json
4
5
6
app = Flask('__name__')
7
8
9
@app.route('/', methods=["GET", "POST", "PUT"])
10
def receive_ping_to_service():
11
time.sleep(3)
12
# message = {"response": "Ping Received, Hello down there from the telemetry service!!"}
13
message = {"response": "Pong"}
14
json_string = json.dumps(message)
15
return json_string
16
17
18
if __name__ == '__main__':
19
app.run(port=8006)

Port mapping

To configure the radio emulator to talk to these apps, you will need to update the port mappings in the javelin-main/javelin-scepter-python_scripts/source/tools/commands/utils.py file. For the above examples, the port mappings looked like the following:
1
port_mapper = {"app": 8000, "monitor": 8030, "scheduler": 8060, "telem": 8006}
2
3
datatype_mapper = {"String": str, "Int": int, "Float": float, "Boolean": bool}

Workbench section 3: sending commands

Before we can send the commands we created in the previous tutorial, we need to activate our KubOS satellite and BBB radio emulator. For this example, we will use the placeholder above. To activate the service applications, simply run each of those scripts. From the Javelin directory, run the radio.py script located in the BBB radio emulator folder. This will activate the radio for the BBB (in our case, the local machine). Once these are all up and running, the commands can be sent.
To send the commands, the execute_operator_cmds function was extracted from the send_cmd_script.py file. This begins the sending process. The Python script for this looked like this.
1
execute_operator_cmds(cmd_lines)
During this period, the terminal will output something similar to:
1
Sending Commands...
2
sending pkt b'\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x00\x00\x00\x00\x1f@{"query": "query{ping}"}'
3
[2022-07-18 06:41:25,540] - commands - INFO - cmd : {"query": "query{ping}"}, num. message sent : 0, num. bytes : 40 - message sent : 00000000002200000000000000001f407b227175657279223a202271756572797b70696e677d227d
4
got back b'\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x1f@{"response": "Pong"}'
5
6
7
Pong
8
sending pkt b'\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x00\x00\x00\x00\x1f^{"query": "query{ping}"}'
9
[2022-07-18 06:41:28,679] - commands - INFO - message received : 0, num bytes : 36, response time : 3.138997 - message received : 00000000001e00000000000000001f407b22726573706f6e7365223a2022506f6e67227d
10
[2022-07-18 06:41:28,680] - commands - INFO - Raw response data:[b'\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x1f@{"response": "Pong"}']
11
[2022-07-18 06:41:28,680] - commands - INFO - cmd : {"query": "query{ping}"}, num. message sent : 0, num. bytes : 40 - message sent : 00000000002200000000000000001f5e7b227175657279223a202271756572797b70696e677d227d
12
got back b'\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x1f^{"response": "Pong"}'
13
14
15
Pong
16
sending pkt b'\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x00\x00\x00\x00\x1f|{"query": "query{ping}"}'
17
[2022-07-18 06:41:31,821] - commands - INFO - message received : 0, num bytes : 36, response time : 3.140506 - message received : 00000000001e00000000000000001f5e7b22726573706f6e7365223a2022506f6e67227d
18
[2022-07-18 06:41:31,821] - commands - INFO - Raw response data:[b'\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x1f^{"response": "Pong"}']
19
[2022-07-18 06:41:31,822] - commands - INFO - cmd : {"query": "query{ping}"}, num. message sent : 0, num. bytes : 40 - message sent : 00000000002200000000000000001f7c7b227175657279223a202271756572797b70696e677d227d
20
[2022-07-18 06:41:34,960] - commands - INFO - message received : 0, num bytes : 36, response time : 3.137528 - message received : 00000000001e00000000000000001f7c7b22726573706f6e7365223a2022506f6e67227d
21
[2022-07-18 06:41:34,960] - commands - INFO - Raw response data:[b'\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x1f|{"response": "Pong"}']
22
[2022-07-18 06:41:34,960] - commands - INFO - cmd : {"query": "query{ping}"}, num. message sent : 0, num. bytes : 40 - message sent : 00000000002200000000000000001f467b227175657279223a202271756572797b70696e677d227d
23
got back b'\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x1f|{"response": "Pong"}'
24
25
26
Pong
27
sending pkt b'\x00\x00\x00\x00\x00"\x00\x00\x00\x00\x00\x00\x00\x00\x1fF{"query": "query{ping}"}'
28
got back b'\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x1fF{"response": "Pong"}'
29
30
31
Pong
32
{'code': 'EXECUTION_END_SUCCESS',
33
'ended_at': '2022-07-11T06:27:32',
34
'instruction_id': 1,
35
'msg': 'Execution end time recorded for instruction'}
36
[2022-07-18 06:41:38,099] - commands - INFO - message received : 0, num bytes : 36, response time : 3.138556 - message received : 00000000001e00000000000000001f467b22726573706f6e7365223a2022506f6e67227d
37
[2022-07-18 06:41:38,099] - commands - INFO - Raw response data:[b'\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x00\x1fF{"response": "Pong"}']
At the end of the command process, the end_contact_instructions function (seen below) is used to tell Scepter that the command instructions have been completed. As you can see, the above output showed the ping commands being sent to each of the services and a successful pong return was received.
1
def end_contact_instructions(sat_id, contact_id, instruction_id):
2
url = base_url + '/satellite/' + sat_id + '/contacts/' + contact_id + '/instructions/' + instruction_id + '/end'
3
filename = "new_satellite/examples/end_satellite_instructions.json"
4
with open(filename, 'r') as f:
5
input_json = json.load(f)
6
response = requests.post(url, headers=headers, json=input_json)
7
return response.json()
and the input is given by:
1
{
2
"ended_at": "2022-07-11T06:27:32",
3
"log": "string"
4
}
Congratulations, you have completed four of the five OSSO tutorials. We can now successfully send a command through our workbench via Javelin and receive a message back. Our final tutorial in this series will look to upgrade this process to account for the orbit of our satellite.
Table of contents