Compilation of .proto
Files
Now that we have installed the compiler and runtime, we can start compiling the
.proto
files. So where are these .proto
files anyway?
Getting .proto
Files
The cTrader OpenAPI publishes its .proto
files in the following GitHub
repository:
https://github.com/spotware/openapi-proto-messages
Let's get a copy of them:
git clone https://github.com/spotware/openapi-proto-messages
if you don't have git
installed on your
system, you can download them manually by going into the page and click the
<> Code
button, and then the Download ZIP
button.
Now that we have the .proto
files in a directory named
openapi-proto-messages
, it's time to compile them.
Compile .proto
Files
Main Compiler
- Windows
- Linux
protoc --proto_path=openapi-proto-messages --python_out=./ ^
OpenApiMessages.proto ^
OpenApiModelMessages.proto ^
OpenApiCommonMessages.proto ^
OpenApiCommonModelMessages.proto
protoc --proto_path=openapi-proto-messages --python_out=./ \
OpenApiMessages.proto \
OpenApiModelMessages.proto \
OpenApiCommonMessages.proto \
OpenApiCommonModelMessages.proto
Now we have the below compiled files:
OpenApiMessages_pb2.py
OpenApiModelMessages_pb2.py
OpenApiCommonMessages_pb2.py
OpenApiCommonModelMessages_pb2.py
Which we will import in our Python code like below:
import OpenApiMessages_pb2.py as OA
import OpenApiModelMessages_pb2.py as OAModel
import OpenApiCommonMessages_pb2.py as OACommon
import OpenApiCommonModelMessages_pb2.py as OACommonModel
JavaScript-Specific Compiler
- Windows
- Linux
cd openapi-proto-messages
pbjs -t json-module -o ../pb.compiled.js --no-beautify --no-comments ^
OpenApiMessages.proto ^
OpenApiModelMessages.proto ^
OpenApiCommonMessages.proto ^
OpenApiCommonModelMessages.proto
cd openapi-proto-messages
pbjs -t json-module -o ../pb.compiled.js --no-beautify --no-comments \
OpenApiMessages.proto \
OpenApiModelMessages.proto \
OpenApiCommonMessages.proto \
OpenApiCommonModelMessages.proto
In the case of JavaScript, we will have one single file as the output of compilation:
pb.compiled.js
Which we will import in our Node.js code like below:
var pb = require('./pb.compiled.js');
Using Pre-Compiled .proto
files from Official Python Package
There is another way to use the compiled .proto
files without actually
compiling them ourselves, and that is through using the
cTrader OpenAPI Official Python Package.
There is also another way to get to use already compiled .proto
files which
exist in the
official Python package. Since
this way we can skip the compilation step, it's worth mentioning. Keep in mind
we still need the runtime in this approach, but we only skip that step because
when we install the official Python package, the runtime is installed with it
(because the runtime is a dependency of it).
So let's create a python virtual environment for an isolated environment and activate it:
python -m venv .env
./env/Scripts/activate
Now let's see what packages we have at this point:
pip list
# Package Version
# ---------- -------
# pip 21.2.3
# setuptools 57.4.0
Now we will intsall the offical cTrader Python package, and after it's done, we will check again to see what packages were installed:
pip install ctrader_open_api
pip list
Which will output a (somewhat) long list of packages that were just installed:
Package Version
------------------- --------
...
...
protobuf 3.20.1
...
...
And there it is, that is the runtime being installed when you install the official Python package, and you can see that its version is much older that the runtime we installed ourself.
When you have an older runtime like here, it can't load .proto
files compiled
with a new compiler. Yes, we're not complining anything here, and that was the
whole point of this section, but hypothetically, if we did, it would be an
example of Cross-Version runtime that was
mentioned earlier.
After we install the official package, we can access the already compiled
.proto
files like below:
import ctrader_open_api.messages.OpenApiMessages_pb2 as OA
import ctrader_open_api.messages.OpenApiModelMessages_pb2 as OAModel
import ctrader_open_api.messages.OpenApiCommonMessages_pb2 as OACommon
import ctrader_open_api.messages.OpenApiCommonModelMessages_pb2 as OAModelCommon
Convert to JSON
As you might have guessed, this approach of using official Python package to
skip the compilation step can be considered a solution if you're using Python,
but what about another programming language? In that case, we can extract the
information in .proto
files and export it into a JSON
format. Altough not an
elegant solution, but still has some value due to it being easy and not needing
the compilation step. (For example in a case where you just want to test
something).
Below is an example of doing so:
import ctrader_open_api.messages.OpenApiModelMessages_pb2 as OAModel
import json
# get payloadTypes
target_keys = filter(lambda i: i.startswith('PROTO_OA_'), dir(OAModel))
out = dict(map(lambda k: [k, getattr(OAModel, k)], target_keys))
out['PROTO_PROTO_MESSAGE' = 5;
out['PROTO_ERROR_RES' = 50;
out['PROTO_HEARTBEAT_EVENT' = 51;
with open('payloadTypes.json', 'w', encoding='utf-8') as f:
json.dump(out, f, ensure_ascii=False, indent=2)
# get OAModel stuff
target_keys = filter(lambda i: i.startswith('ProtoOA'), dir(OAModel))
ones_with_keyval = filter(lambda k: hasattr(getattr(OAModel,k),'keys'), target_keys)
out = {}
for key in ones_with_keyval:
prop = getattr(OAModel, key)
out[key] = dict(zip(prop.keys(), prop.values()))
with open('OAModel.json', 'w', encoding='utf-8') as f:
json.dump(out, f, ensure_ascii=False, indent=2)
Keep in mind, in this approach, the naming of the messages change from
PascalCase
to UPPER_SNAKE_CASE
(aka SCREAMING_SNAKE_CASE
), unless you
modify the code otherwise.