Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
python.cpp 9.55 KiB
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>

#include "CharDeviceCom.h"
#include "ComRegistry.h"
#include "GPIBSerialCom.h"
#include "ICom.h"
#include "SerialCom.h"
#include "TextSerialCom.h"
#include "nlohmann/json.hpp"
#include "pybind11_json/pybind11_json.hpp"

namespace py = pybind11;

class PyICom : public ICom {
 public:
    /* Inherit the constructors */
    using ICom::ICom;

    void init() override { PYBIND11_OVERLOAD_PURE(void, ICom, init, ); }
    void setConfiguration(const nl::json &config) override {
        PYBIND11_OVERLOAD_PURE(void, ICom, setConfiguration, config);
    }
    void send(char *buf, size_t length) override {
        PYBIND11_OVERLOAD_PURE(void, ICom, send, buf, length);
    }
    void send(const std::string &buf) override {
        PYBIND11_OVERLOAD_PURE(void, ICom, send, buf);
    }
    std::string receive() override {
        PYBIND11_OVERLOAD_PURE(std::string, ICom, receive, );
    }
    uint32_t receive(char *buf, size_t length) override {
        PYBIND11_OVERLOAD_PURE(uint32_t, ICom, receive, buf, length);
    }
    std::string sendreceive(const std::string &cmd) override {
        PYBIND11_OVERLOAD_PURE(std::string, ICom, sendreceive, cmd);
    }
    void sendreceive(char *wbuf, size_t wlength, char *rbuf,
                     size_t rlength) override {
        PYBIND11_OVERLOAD_PURE(void, ICom, sendreceive, wbuf, wlength, rbuf,
                               rlength);
    }
    void lock() override { PYBIND11_OVERLOAD_PURE(void, ICom, lock, ); }
    void unlock() override { PYBIND11_OVERLOAD_PURE(void, ICom, unlock, ); }
};

// template trampoline to reduce code duplication
template <class ComBase = SerialCom>
class PyCom : public ComBase {
 public:
    /* Inherit the constructors */
    using ComBase::ComBase;

    void init() override { PYBIND11_OVERLOAD(void, ComBase, init, ); }
    void setConfiguration(const nl::json &config) override {
        PYBIND11_OVERLOAD(void, ComBase, setConfiguration, config);
    }
    void send(char *buf, size_t length) override {
        PYBIND11_OVERLOAD(void, ComBase, send, buf, length);
    }
    void send(const std::string &buf) override {
        PYBIND11_OVERLOAD(void, ComBase, send, buf);
    }
    std::string receive() override {
        PYBIND11_OVERLOAD(std::string, ComBase, receive, );
    }
    uint32_t receive(char *buf, size_t length) override {
        PYBIND11_OVERLOAD(uint32_t, ComBase, receive, buf, length);
    }
    std::string sendreceive(const std::string &cmd) override {
        PYBIND11_OVERLOAD(std::string, ComBase, sendreceive, cmd);
    }
    void sendreceive(char *wbuf, size_t wlength, char *rbuf,
                     size_t rlength) override {
        PYBIND11_OVERLOAD(void, ComBase, sendreceive, wbuf, wlength, rbuf,
                          rlength);
    }
    void lock() override { PYBIND11_OVERLOAD(void, ComBase, lock, ); }
    void unlock() override { PYBIND11_OVERLOAD(void, ComBase, unlock, ); }
};

class PyTextSerialCom : public TextSerialCom {
 public:
    /* Inherit the constructors */
    using TextSerialCom::TextSerialCom;

    void setConfiguration(const nl::json &config) override {
        PYBIND11_OVERLOAD(void, TextSerialCom, setConfiguration, config);
    }
    void send(char *buf, size_t length) override {
        PYBIND11_OVERLOAD(void, TextSerialCom, send, buf, length);
    }
    void send(const std::string &buf) override {
        PYBIND11_OVERLOAD(void, TextSerialCom, send, buf);
    }
    std::string receive() override {
        PYBIND11_OVERLOAD(std::string, TextSerialCom, receive, );
    }
    uint32_t receive(char *buf, size_t length) override {
        PYBIND11_OVERLOAD(uint32_t, TextSerialCom, receive, buf, length);
    }
};

class PyGPIBSerialCom : public GPIBSerialCom {
 public:
    /* Inherit the constructors */
    using GPIBSerialCom::GPIBSerialCom;

    void init() override { PYBIND11_OVERLOAD(void, PyGPIBSerialCom, init, ); }
    void setConfiguration(const nl::json &config) override {
        PYBIND11_OVERLOAD(void, GPIBSerialCom, setConfiguration, config);
    }
    void send(char *buf, size_t length) override {
        PYBIND11_OVERLOAD(void, GPIBSerialCom, send, buf, length);
    }
    void send(const std::string &buf) override {
        PYBIND11_OVERLOAD(void, GPIBSerialCom, send, buf);
    }
    std::string receive() override {
        PYBIND11_OVERLOAD(std::string, GPIBSerialCom, receive, );
    }
    uint32_t receive(char *buf, size_t length) override {
        PYBIND11_OVERLOAD(uint32_t, GPIBSerialCom, receive, buf, length);
    }
};

void register_com(py::module &m) {
    py::class_<ICom, PyICom, std::shared_ptr<ICom>>(m, "ICom")
        .def(py::init())
        .def("init", &ICom::init)
        .def("is_open", &ICom::is_open)
        .def("setConfiguration", &ICom::setConfiguration)
        .def("send", (void (ICom::*)(char *, size_t)) & ICom::send)
        .def("send", (void (ICom::*)(const std::string &)) & ICom::send)
        .def("receive", (std::string(ICom::*)()) & ICom::receive)
        .def("receive", (uint32_t(ICom::*)(char *, size_t)) & ICom::receive)
        .def("sendreceive",
             (std::string(ICom::*)(const std::string &)) & ICom::sendreceive)
        .def("sendreceive", (void (ICom::*)(char *, size_t, char *, size_t)) &
                                ICom::sendreceive)
        .def("lock", &ICom::lock)
        .def("unlock", &ICom::unlock);

    py::class_<CharDeviceCom, PyCom<CharDeviceCom>, ICom,
               std::shared_ptr<CharDeviceCom>>(m, "CharDeviceCom")
        .def(py::init<const std::string &>());

    py::class_<SerialCom, PyCom<SerialCom>, ICom, std::shared_ptr<SerialCom>>
        py_serialcom(m, "SerialCom");
    // nb: enum defined first because it is used in py_serialcom init() default
    py::enum_<SerialCom::BaudRate>(py_serialcom, "BaudRate")
        .value("Baud0", SerialCom::BaudRate::Baud0)
        .value("Baud50", SerialCom::BaudRate::Baud50)
        .value("Baud75", SerialCom::BaudRate::Baud75)
        .value("Baud110", SerialCom::BaudRate::Baud110)
        .value("Baud134", SerialCom::BaudRate::Baud134)
        .value("Baud150", SerialCom::BaudRate::Baud150)
        .value("Baud200", SerialCom::BaudRate::Baud200)
        .value("Baud300", SerialCom::BaudRate::Baud300)
        .value("Baud600", SerialCom::BaudRate::Baud600)
        .value("Baud1200", SerialCom::BaudRate::Baud1200)
        .value("Baud1800", SerialCom::BaudRate::Baud1800)
        .value("Baud2400", SerialCom::BaudRate::Baud2400)
        .value("Baud4800", SerialCom::BaudRate::Baud4800)
        .value("Baud9600", SerialCom::BaudRate::Baud9600)
        .value("Baud19200", SerialCom::BaudRate::Baud19200)
        .value("Baud38400", SerialCom::BaudRate::Baud38400)
        .value("Baud57600", SerialCom::BaudRate::Baud57600)
        .value("Baud115200", SerialCom::BaudRate::Baud115200)
        .value("Baud230400", SerialCom::BaudRate::Baud230400)
        .value("Baud460800", SerialCom::BaudRate::Baud460800)
        .value("Baud500000", SerialCom::BaudRate::Baud500000)
        .value("Baud576000", SerialCom::BaudRate::Baud576000)
        .value("Baud921600", SerialCom::BaudRate::Baud921600)
        .value("Baud1000000", SerialCom::BaudRate::Baud1000000)
        .value("Baud1152000", SerialCom::BaudRate::Baud1152000)
        .value("Baud1500000", SerialCom::BaudRate::Baud1500000)
        .value("Baud2000000", SerialCom::BaudRate::Baud2000000)
        .value("Baud2500000", SerialCom::BaudRate::Baud2500000)
        .value("Baud3000000", SerialCom::BaudRate::Baud3000000)
        .value("Baud3500000", SerialCom::BaudRate::Baud3500000)
        .value("Baud4000000", SerialCom::BaudRate::Baud4000000);

    py::enum_<SerialCom::CharSize>(py_serialcom, "CharSize")
        .value("CharSize5", SerialCom::CharSize::CharSize5)
        .value("CharSize6", SerialCom::CharSize::CharSize6)
        .value("CharSize7", SerialCom::CharSize::CharSize7)
        .value("CharSize8", SerialCom::CharSize::CharSize8);

    py_serialcom
        .def(py::init<const std::string &, SerialCom::BaudRate, bool, bool,
                      bool, SerialCom::CharSize>(),
             py::arg("port"), py::arg("baud") = SerialCom::BaudRate::Baud19200,
             py::arg("parityBit") = false, py::arg("twoStopBits") = false,
             py::arg("flowControl") = false,
             py::arg("charsize") = SerialCom::CharSize::CharSize8)
        .def("flush", &SerialCom::flush)
        .def("setTimeout", &SerialCom::setTimeout);

    py::class_<TextSerialCom, PyTextSerialCom, SerialCom,
               std::shared_ptr<TextSerialCom>>(m, "TextSerialCom")
        .def(py::init<const std::string &, SerialCom::BaudRate, bool, bool,
                      bool, SerialCom::CharSize>(),
             py::arg("port"), py::arg("baud") = SerialCom::BaudRate::Baud19200,
             py::arg("parityBit") = false, py::arg("twoStopBits") = false,
             py::arg("flowControl") = false,
             py::arg("charsize") = SerialCom::CharSize::CharSize8)
        .def("setTermination", &TextSerialCom::setTermination)
        .def("termination", &TextSerialCom::termination);

    py::class_<GPIBSerialCom, PyGPIBSerialCom, TextSerialCom,
               std::shared_ptr<GPIBSerialCom>>(m, "GPIBSerialCom")
        .def(py::init<uint16_t, const std::string &, SerialCom::BaudRate, bool,
                      bool, bool, SerialCom::CharSize>(),
             py::arg("gpib_addr"), py::arg("port"),
             py::arg("baud") = SerialCom::BaudRate::Baud19200,
             py::arg("parityBit") = false, py::arg("twoStopBits") = false,
             py::arg("flowControl") = false,
             py::arg("charsize") = SerialCom::CharSize::CharSize8);

    m.def("listCom", &EquipRegistry::listCom);
}